Відповіді:
Коли ви робите запит POST, ви повинні кодувати дані, які певним чином формують тіло запиту.
Форми HTML забезпечують три способи кодування.
application/x-www-form-urlencoded
(за замовчуванням)multipart/form-data
text/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-urlencoded
multipart/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, nc
BSD 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
, ми б не хотіли цього, бо це настільки неефективно.
Але для друкованих символів, знайдених у текстових полях, це не має значення і створює менше накладних витрат, тому ми просто використовуємо це.
%CF
3 байта довжиною: %
, 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-data
RFC, але тим не менше це довільна звалище міркувань безпеки про подання форм, які повністю ортогональні чи дані , що передаються в якості 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.