Що означає enctype = "багаточастинні / форми-дані"?


Відповіді:


1570

Коли ви робите запит 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 і корисний лише для налагодження - із специфікації : їх не можна надійно інтерпретувати на комп’ютері - і я можу стверджувати, що інші, комбіновані з інструментами (наприклад, Мережева панель в інструментах розробників більшості браузерів), краще для того).


5
@Quentin Вибачте, яка буде будь-яка ймовірна проблема, якщо ми використовуватимемо мультичастину для всіх форм? з файлами та відбілити їх.
Вебінан

12
Це не має сенсу для форм GET, і це збільшує розмір файлів запитів.
Квентін

@Quentin, чи надсилаються багатоповерхові дані у формі потоку за замовчуванням?
Гроулер

Чи означає, що enc в enctype щось означає?
Філіп Рего

1
"HTML форми надають три методи ENC ",
Квентін

449

коли ми повинні ним користуватися

Відповідь Квентіна правильна: використовуйте, multipart/form-dataякщо форма містить завантаження файлу, application/x-www-form-urlencodedінакше, що за замовчуванням, якщо ви пропустите enctype.

Я збираюсь:

  • додати ще кілька посилань HTML5
  • поясніть, чому він має рацію, надіславши приклад форми

Посилання HTML5

Існує три можливості для enctype:

  • application/x-www-form-urlencoded
  • multipart/form-data(специфікація вказує на RFC7578 )
  • text/plain. Це "не можна надійно інтерпретувати за допомогою комп'ютера", тому його ніколи не слід використовувати у виробництві, і ми далі не будемо його розбирати.

Як генерувати приклади

Як тільки ви бачите приклад кожного методу, стає очевидним, як вони працюють, і коли ви повинні використовувати кожен з них.

Ви можете навести приклади, використовуючи:

Збережіть форму в мінімальному .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&#x03C9;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&#x03C9;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 завантаженого файлу?

додаток / x-www-form-urlencoded

Тепер змініть 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, ми б не хотіли цього, бо це настільки неефективно.

Але для друкованих символів, знайдених у текстових полях, це не має значення і створює менше накладних витрат, тому ми просто використовуємо це.


3
@ Khanna111 %CF3 байта довжиною: %, Cі F:-) Історія робить його читаним людиною.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

6
В OS X ncне приймати одночасно -lі -pаргументи, і аргументи. Але це працює для мене: while true; do printf '' | nc -l 8000; done.
PhilipS

4
Невеликий, але важливий момент, який не згадується, полягає в тому, що межа, зазначена у значенні, Content-Typeмає два дефіси ( --) менше, тобто, коли фактично використовується межа в тілі повідомлення, ви повинні встановити його за допомогою префікса --. Також останній кордон повинен бути суфіксом --, але це досить легко помітити. Дивіться stackoverflow.com/questions/3508252/…
Бернар

1
Наскільки я можу сказати, сенс ставити БУДЬ-ЯКІ ПОРУШЕННЯ ВСІ в межі полягає в тому, що неможливо перевірити синтаксис запиту оком. Будь ласка, не використовуйте їх у своїх обмежених жетонах.
Дьюї Морган

1
@DewiMorgan Ви абсолютно праві. Я відредагував пост і вилучив тире з граничного рядка.
Макс

91

enctype='multipart/form-dataце тип кодування, який дозволяє надсилати файли через POST . Простіше кажучи, без цього кодування файли не можуть надсилатися через POST .

Якщо ви хочете дозволити користувачеві завантажувати файл через форму, ви повинні використовувати цю ентепію .


Отже .. якщо файл не є двійковим файлом, то чи можемо ми працювати без цього?
Yugal Jindle

Як я розумію, ви можете використовувати multipart/form-dataдля надсилання небінарних файлів, але це неефективно. Я вважаю, що використання application/x-www-form-urlencoded- це правильний спосіб надсилання небінарних даних, але, можливо, хтось із більшим досвідом роботи з небінарними файлами може мене виправити.
Метт Есбері

11
Основна перевага для використання multipart/form-dataдля надсилання файлу полягає в тому, що він буде працювати автоматично як у фронте, так і в бекенді. Вам не потрібно робити ніяких спеціальних операцій. Усі файли є двійковими, навіть якщо вони повинні містити лише текст. application/x-www-form-urlencodedє стандартним способом розміщення форми без доданих файлів. multipart/form-dataє стандартним способом розміщення форми з доданими файлами. (Є також численні інші кодування, такі як application/jsonі application/json-patch+json, які є загальними для спілкування між сервером і клієнтом.)
Даніель Луна,

6
Варто вказати, що ви можете base64 кодувати ваше зображення та надсилати його як звичайні рядкові дані.
Джеймс

3
Далі до коментаря @ Prospero вище: ви можете абсолютно надсилати файли через POST без використання multipart/form-data. Що ви не можете зробити, це зробити це, використовуючи звичайну HTML-форму, без JavaScript. Налаштування форми для використання multipart/form-data- єдиний механізм, який надає HTML, щоб ви могли розміщувати файли POST без використання JavaScript. Я відчуваю, що у відповіді це недостатньо зрозуміло, і що наївний читач може подумати, що неможливість надсилання файлів без multipart/form-dataобмеження HTTP ; це не так.
Марк Амері

81

Подаючи форму, ви повідомляєте вашому браузеру надсилати через протокол 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: Дані форми з декількома частинами - Міркування щодо безпеки :

Все програмне забезпечення для обробки форм повинне ставитись до наданих користувачем форм-даних
з чутливістю, оскільки воно часто містить конфіденційну або особисту
інформацію. У веб-браузерах широко застосовуються функції форми автоматичного заповнення; вони можуть бути використані для обману користувачів, щоб
несвідомо надсилати конфіденційну інформацію при виконанні
завдань, що не є нешкідливими. багаточастинні дані / форми не надають жодних функцій
для перевірки цілісності, забезпечення конфіденційності, уникнення
плутанини користувачів або інших функцій безпеки; ці проблеми повинні
вирішуватися додатками для заповнення форми та інтерпретації даних.

Програми, які отримують форми та обробляють їх, повинні бути обережними, щоб не повертати дані на запитуючий веб-сайт, який не збирався надсилати.

Важливо при інтерпретації назви файла
поля заголовка вмісту- диспозиції не випадково перезаписувати файли у
файловому просторі одержувача.

Це стосується вас, якщо ви розробник, і ваш сервер буде обробляти форми, подані користувачами, які можуть містити конфіденційну інформацію.


1
Інформація про безпеку після останнього редагування не має значення для питання, що enctypeробити. Я знаю , що буквально з multipart/form-dataRFC, але тим не менше це довільна звалище міркувань безпеки про подання форм, які повністю ортогональні чи дані , що передаються в якості application/x-www-form-urlencodedабо multipart/form-data.
Марк Амері

38

enctype='multipart/form-data'означає, що жодні символи не будуть закодовані. саме тому цей тип використовується під час завантаження файлів на сервер.
Так multipart/form-dataвикористовується, коли форма вимагає завантаження двійкових даних, як-от вмісту файлу


8

Встановіть атрибут методу на POST, оскільки вміст файлу не можна вводити всередині параметра URL за допомогою форми.

Встановіть значення enctype на багаточастинні / форм-дані, оскільки дані будуть розділені на кілька частин, по одній для кожного файлу плюс одна для тексту тіла форми, який може бути надісланий разом з ними.


Це означає, що POST, ймовірно, буде достатньо для надсилання файлу через форму, і додавання multipart/form-data- це лише бонус у певній мірі. Це не так. Більшість файлів абсолютно потребують використання multipart/form-data.
підкреслюй__11

1
  • атрибут enctype ( ENC ode TYPE ) визначає, як дані форми форми повинні кодуватися під час подання їх на сервер.
  • multipart / form-data - одне із значень атрибута enctype, який використовується у елементі форми, який має завантаження файлу. багаточастинні засоби форми даних ділять на кілька частин і надсилають на сервер.

5
Я вважаю, що енктип не означає тип шифрування. На цьому рівні не задіяно шифрування. Думаю, це або тип кодування, або тип закритого типу. Але, безумовно, це не тип шифрування.
Єо

1
Ваша остання точка кулі тут про <head>і не <body>стосується і заплутує.
Марк Амері

0

Зазвичай це тоді, коли у вас є форма POST, яка повинна сприймати завантаження файлу як дані ... це підкаже серверу, як він буде кодувати передані дані, у такому випадку він не буде закодований, оскільки він просто перенесе та завантажить файли на сервер, як, наприклад, під час завантаження зображення або PDF


-3

Атрибут enctype визначає, як повинні бути закодовані дані форми-форми при поданні їх на сервер.

Атрибут enctype може використовуватися лише в тому випадку, якщо method = "post".

Жодні символи не кодуються. Це значення потрібно, коли ви використовуєте форми, які мають контроль завантаження файлів

З W3Schools


2
Ця цитата навіть не згадує multipart/form-data. Це також досить незрозуміло; що означає навіть речення "Жодні символи не закодовані"? -1.
Марк Амері
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.