Відповіді:
Коли ви робите запит POST, ви повинні кодувати дані, які певним чином формують тіло запиту.
Форми HTML забезпечують три способи кодування.
application/x-www-form-urlencoded (за замовчуванням)multipart/form-datatext/plainПроводилася робота над додаванням application/json, але це було відмовлено.
(Можливі інші кодування із запитами HTTP, згенерованими за допомогою інших засобів, ніж подання форми HTML. JSON - це звичайний формат для використання з веб-службами, а деякі все ще використовують SOAP.)
Специфіка форматів не має значення для більшості розробників. Важливі моменти:
text/plain.Коли ви пишете код на стороні клієнта:
multipart/form-dataколи ваша форма включає будь-які <input type="file">елементиmultipart/form-dataабо , application/x-www-form-urlencodedале application/x-www-form-urlencodedбуде більш ефективнимКоли ви пишете код на стороні сервера:
Більшість (наприклад, Perl CGI->paramабо той, який піддається $_POSTсуперглобалу PHP ) подбають про відмінності за вас. Не турбуйтеся намагатися проаналізувати необроблений вхід, отриманий сервером.
Іноді ви знайдете бібліотеку, яка не може працювати з обома форматами. Найпопулярніша бібліотека Node.js для обробки даних форми - це тісний аналізатор, який не може обробляти багатопотужні запити (але має документацію, яка рекомендує деякі можливі варіанти).
Якщо ви пишете (або налагоджуєте) бібліотеку для розбору або генерування необроблених даних, то вам потрібно почати турбуватися про формат. Ви також можете дізнатися про це заради інтересів.
application/x-www-form-urlencoded більше або менш збігається з рядком запиту в кінці URL-адреси.
multipart/form-dataзначно складніший, але він дозволяє включати цілі файли до даних. Приклад результату можна знайти в специфікації HTML 4 .
text/plainзапроваджений HTML 5 і корисний лише для налагодження - із специфікації : їх не можна надійно інтерпретувати на комп’ютері - і я можу стверджувати, що інші, комбіновані з інструментами (наприклад, Мережева панель в інструментах розробників більшості браузерів), краще для того).
коли ми повинні ним користуватися
Відповідь Квентіна правильна: використовуйте, multipart/form-dataякщо форма містить завантаження файлу, application/x-www-form-urlencodedінакше, що за замовчуванням, якщо ви пропустите enctype.
Я збираюсь:
Існує три можливості для enctype:
application/x-www-form-urlencodedmultipart/form-data(специфікація вказує на RFC7578 )text/plain. Це "не можна надійно інтерпретувати за допомогою комп'ютера", тому його ніколи не слід використовувати у виробництві, і ми далі не будемо його розбирати.Як тільки ви бачите приклад кожного методу, стає очевидним, як вони працюють, і коли ви повинні використовувати кожен з них.
Ви можете навести приклади, використовуючи:
nc -lабо ECHO-сервер: тестовий сервер HTTP, що приймає GET / POST-запитиЗбережіть форму в мінімальному .htmlфайлі:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
</body>
</html>
Ми встановлюємо текстове значення за замовчуванням на aωb, що означає, aωbщо ωє U+03C9, які є байтами 61 CF 89 62в UTF-8.
Створіть файли для завантаження:
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary
Запустіть наш маленький ехо-сервер:
while true; do printf '' | nc -l 8000 localhost; done
Відкрийте HTML у своєму браузері, виберіть файли та натисніть кнопку "Подати та перевірити" термінал.
nc друкує отриманий запит.
Тестовано на: Ubuntu 14.04.3, ncBSD 1.105, Firefox 40.
Firefox надіслано:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
Для бінарного файлу та текстового поля байти 61 CF 89 62( aωbв UTF-8) надсилаються буквально. Ви можете переконатись у тому nc -l localhost 8000 | hd, що говорить, що байти:
61 CF 89 62
були надіслані ( 61== 'a' і 62== 'b').
Тому зрозуміло, що:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150встановлює тип вмісту multipart/form-dataта каже, що поля розділені заданим boundaryрядком.
Але зауважте, що:
boundary=---------------------------735323031399963166993862150
має два менші тири, --ніж фактичний бар'єр
-----------------------------735323031399963166993862150
Це тому, що стандарт вимагає, щоб межа починалася з двох тире --. Інші тире виглядають лише як Firefox вирішив реалізувати довільну межу. RFC 7578 чітко зазначає, що --потрібні ці два провідні тире :
4.1. Параметр "Межі" багаточастинкових / форм-даних
Як і в інших типів з кількома частинами, деталі розмежовані граничним роздільником, побудованим за допомогою CRLF, "-" та значення параметра "межа".
кожне поле отримує деякі підзаголовки перед своїми даними:, Content-Disposition: form-data;поле name, the filename, за якими йдуть дані.
Сервер зчитує дані до наступного граничного рядка. Веб-переглядач повинен вибрати межу, яка не відображатиметься в жодному з полів, тому межа може залежати від запитів.
Оскільки у нас є унікальна межа, кодування даних не потрібно: двійкові дані надсилаються як є.
TODO: який оптимальний розмір межі ( log(N)я ставлю ставку) та ім'я / час виконання алгоритму, який його знаходить? На запитання: /cs/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences
Content-Type автоматично визначається браузером.
Як саме це визначено, запитували на: Як визначається браузер браузером типу mime завантаженого файлу?
Тепер змініть enctypeна application/x-www-form-urlencoded, перезавантажте веб-переглядач та повторно надішліть.
Firefox надіслано:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
Очевидно, що дані файлу не надсилалися, лише базові імена. Тож це не можна використовувати для файлів.
Що стосується текстового поля, ми бачимо , що звичайні друковані символи , як aі bбули відправлені в один байт, в той час як недруковані з них , як 0xCFі 0x89зайняв 3 байта кожен: %CF%89!
Завантаження файлів часто містить безліч символів, які не можна надрукувати (наприклад, зображення), а текстові форми майже ніколи не роблять.
З прикладів ми бачили, що:
multipart/form-data: додає в повідомлення кілька байтів граничних накладних даних і потрібно витратити якийсь час на його обчислення, але надсилає кожен байт в одному байті.
application/x-www-form-urlencoded: має одну байтову межу на поле ( &), але додає лінійний накладний коефіцієнт 3x для кожного недрукуваного символу.
Тому навіть якби ми могли надсилати файли application/x-www-form-urlencoded, ми б не хотіли цього, бо це настільки неефективно.
Але для друкованих символів, знайдених у текстових полях, це не має значення і створює менше накладних витрат, тому ми просто використовуємо це.
%CF3 байта довжиною: %, Cі F:-) Історія робить його читаним людиною.
ncне приймати одночасно -lі -pаргументи, і аргументи. Але це працює для мене: while true; do printf '' | nc -l 8000; done.
Content-Typeмає два дефіси ( --) менше, тобто, коли фактично використовується межа в тілі повідомлення, ви повинні встановити його за допомогою префікса --. Також останній кордон повинен бути суфіксом --, але це досить легко помітити. Дивіться stackoverflow.com/questions/3508252/…
enctype='multipart/form-dataце тип кодування, який дозволяє надсилати файли через POST . Простіше кажучи, без цього кодування файли не можуть надсилатися через POST .
Якщо ви хочете дозволити користувачеві завантажувати файл через форму, ви повинні використовувати цю ентепію .
multipart/form-dataдля надсилання небінарних файлів, але це неефективно. Я вважаю, що використання application/x-www-form-urlencoded- це правильний спосіб надсилання небінарних даних, але, можливо, хтось із більшим досвідом роботи з небінарними файлами може мене виправити.
multipart/form-dataдля надсилання файлу полягає в тому, що він буде працювати автоматично як у фронте, так і в бекенді. Вам не потрібно робити ніяких спеціальних операцій. Усі файли є двійковими, навіть якщо вони повинні містити лише текст. application/x-www-form-urlencodedє стандартним способом розміщення форми без доданих файлів. multipart/form-dataє стандартним способом розміщення форми з доданими файлами. (Є також численні інші кодування, такі як application/jsonі application/json-patch+json, які є загальними для спілкування між сервером і клієнтом.)
multipart/form-data. Що ви не можете зробити, це зробити це, використовуючи звичайну HTML-форму, без JavaScript. Налаштування форми для використання multipart/form-data- єдиний механізм, який надає HTML, щоб ви могли розміщувати файли POST без використання JavaScript. Я відчуваю, що у відповіді це недостатньо зрозуміло, і що наївний читач може подумати, що неможливість надсилання файлів без multipart/form-dataобмеження HTTP ; це не так.
Подаючи форму, ви повідомляєте вашому браузеру надсилати через протокол HTTP повідомлення в мережі, належним чином укладене в структуру повідомлень протоколу TCP / IP. На сторінці HTML є спосіб надсилання даних на сервер: за допомогою <form>s.
Коли подається форма, створюється запит HTTP та надсилається серверу, повідомлення буде містити назви полів у формі та значення, заповнені користувачем. Ця передача може відбуватися за допомогою POSTабо GET HTTP-методів .
POST повідомляє веб-переглядачу створити HTTP-повідомлення та помістити весь вміст у тіло повідомлення (дуже корисний спосіб робити, більш безпечний і гнучкий).GETподасть дані форми у рядок запитів . Він має деякі обмеження щодо представлення даних та їх довжини.Атрибут enctypeмає сенс лише при використанні POSTметоду. Якщо зазначено, він вказує браузеру надсилати форму, кодуючи її вміст певним чином. Від MDN - Енцип форми :
Коли значення атрибуту методу є post, enctype - це тип вмісту MIME, який використовується для подання форми на сервер.
application/x-www-form-urlencoded: Це за замовчуванням. Коли форма надіслана, всі імена та значення збираються, а в остаточному рядку виконується кодування URL-адрес .multipart/form-data: Символи НЕ кодуються. Це важливо, коли у формі є контроль завантаження файлів. Ви хочете надіслати файл бінарним, і це гарантує, що бітовий потік не буде змінено.text/plain: Простори перетворюються, але більше кодування не виконується.Подаючи форми, можуть виникнути певні проблеми із безпекою, як зазначено в RFC 7578 Розділ 7: Дані форми з декількома частинами - Міркування щодо безпеки :
Все програмне забезпечення для обробки форм повинне ставитись до наданих користувачем форм-даних
з чутливістю, оскільки воно часто містить конфіденційну або особисту
інформацію. У веб-браузерах широко застосовуються функції форми автоматичного заповнення; вони можуть бути використані для обману користувачів, щоб
несвідомо надсилати конфіденційну інформацію при виконанні
завдань, що не є нешкідливими. багаточастинні дані / форми не надають жодних функцій
для перевірки цілісності, забезпечення конфіденційності, уникнення
плутанини користувачів або інших функцій безпеки; ці проблеми повинні
вирішуватися додатками для заповнення форми та інтерпретації даних.Програми, які отримують форми та обробляють їх, повинні бути обережними, щоб не повертати дані на запитуючий веб-сайт, який не збирався надсилати.
Важливо при інтерпретації назви файла
поля заголовка вмісту- диспозиції не випадково перезаписувати файли у
файловому просторі одержувача.
Це стосується вас, якщо ви розробник, і ваш сервер буде обробляти форми, подані користувачами, які можуть містити конфіденційну інформацію.
enctypeробити. Я знаю , що буквально з multipart/form-dataRFC, але тим не менше це довільна звалище міркувань безпеки про подання форм, які повністю ортогональні чи дані , що передаються в якості application/x-www-form-urlencodedабо multipart/form-data.
Встановіть атрибут методу на POST, оскільки вміст файлу не можна вводити всередині параметра URL за допомогою форми.
Встановіть значення enctype на багаточастинні / форм-дані, оскільки дані будуть розділені на кілька частин, по одній для кожного файлу плюс одна для тексту тіла форми, який може бути надісланий разом з ними.
POST, ймовірно, буде достатньо для надсилання файлу через форму, і додавання multipart/form-data- це лише бонус у певній мірі. Це не так. Більшість файлів абсолютно потребують використання multipart/form-data.
<head>і не <body>стосується і заплутує.
Зазвичай це тоді, коли у вас є форма POST, яка повинна сприймати завантаження файлу як дані ... це підкаже серверу, як він буде кодувати передані дані, у такому випадку він не буде закодований, оскільки він просто перенесе та завантажить файли на сервер, як, наприклад, під час завантаження зображення або PDF
Атрибут enctype визначає, як повинні бути закодовані дані форми-форми при поданні їх на сервер.
Атрибут enctype може використовуватися лише в тому випадку, якщо method = "post".
Жодні символи не кодуються. Це значення потрібно, коли ви використовуєте форми, які мають контроль завантаження файлів
multipart/form-data. Це також досить незрозуміло; що означає навіть речення "Жодні символи не закодовані"? -1.