Как должен выглядеть составной HTTP-запрос с несколькими файлами?

Я работаю над приложением для iPhone, которое делает составной HTTP-запрос с несколькими файлами изображений.

Похоже, что на стороне сервера происходит то, что одно из изображений обрабатывается правильно, а два других файла — нет.

Может ли кто-нибудь опубликовать образец составного HTTP-запроса, содержащего несколько файлов изображений?


person bpapa    schedule 27.05.2009    source источник


Ответы (2)


Обратите внимание, что запрос содержит двоичные данные, поэтому я не публикую запрос как таковой — вместо этого я преобразовал каждый непечатаемый символ ascii в точку (".").

POST /cgi-bin/qtest HTTP/1.1
Host: aram
User-Agent: Mozilla/5.0 Gecko/2009042316 Firefox/3.0.10
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://aram/~martind/banner.htm
Content-Type: multipart/form-data; boundary=2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Length: 514

--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile1"; filename="r.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile2"; filename="g.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile3"; filename="b.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f--

Обратите внимание, что каждая строка (включая последнюю) заканчивается последовательностью \r\n.

person Daniel Martin    schedule 27.05.2009
comment
просто чтобы избежать путаницы: обратите внимание, что перед каждой граничной строкой в ​​содержимом есть два дополнительных дефиса --‹boundary›. Ибо последняя строка --‹граница›-- - person Radu Simionescu; 14.06.2013
comment
Любые хорошие идеи о том, как создать составной файл, подобный этому, с циклом for? Моя проблема заключается в этом дополнительном -- перед окончательным \r\n. Если бы это было только в конце, я мог бы добавить его ... Можно ли было бы проверить, были ли вы в конечном объекте в своем массиве цикла for и добавить что-то другое? - person turkeyhundt; 21.10.2014
comment
@turkeyhundt - сразу приходят на ум два варианта: 1) напишите свой цикл как (печатать границу, печатать материал), а затем, после завершения цикла for, за ним следует (печатать границу с дополнительными тире). Это, наверное, самый простой способ. 2) напишите свой цикл for() для запуска любой индексной переменной, которая у вас есть, до 0, а не вверх от 0. Затем добавьте два дополнительных тире, когда вы печатаете границу в конце, если индексная переменная равна 0. - person Daniel Martin; 24.10.2014
comment
Это действительно НЕ хороший пример. Почему вы выбрали границу, в которой уже есть -- для примера. Если кто-то не знает, что эта граница - это снова с префиксом еще 2 --, вы облажались. - person Erik Aigner; 05.06.2015
comment
Хотя это именно то, что мой веб-браузер выдал в то время. Реальные браузеры используют границы с большим количеством дефисов. - person Daniel Martin; 05.06.2015
comment
Да, браузеры ставят тире в границах. Лучше люди узнают в этом ответе, чем позже. - person sudo; 08.08.2015
comment
Для каждой записи файла поле «имя» автоматически создается браузером? (речь о «файле данных3», «файле данных2», «файле данных1») Если не создается автоматически, откуда эти значения заполняются? Браузер позволяет пользователю выбирать несколько файлов для ввода одного файла в формате html. - person Dhanaraj Durairaj; 18.03.2016
comment
Есть одна причудливая ситуация, о которой никто не упоминает: границы могут быть завернуты одна в другую! Посмотрите последний пример на W3: w3.org/ TR/html4/interact/forms.html#h-17.13.4.2 Мы определяем первую границу A, затем используем ее (--A), затем определяем вторую границу B, затем используем ее (--B ), затем мы завершаем сначала внутреннюю границу (--B--), затем внешнюю границу (--A--). - person Ignas2526; 20.06.2017
comment
Можно ли упредить полное получение составного запроса. Скажем, я отправляю большую полезную нагрузку и отправляю немного метаданных об этой полезной нагрузке, чтобы сервер мог выполнить некоторые проверки и раньше отклонить запрос, если некоторые условия не выполняются. В настоящее время я получаю полный запрос, а затем выполняю проверку, но кажется излишним получать и сохранять полезную нагрузку даже временно, если запрос в конечном итоге должен быть отклонен сервером. Я могу отправить метаданные в начале запроса, а затем полезную нагрузку. - person Web User; 20.06.2018

EDIT: я поддерживаю аналогичный, но более подробный ответ по адресу: https://stackoverflow.com/a/28380690/895245

Чтобы точно увидеть, что происходит, используйте nc -l и пользовательский агент, такой как браузер или cURL.

Сохраните форму в файл .html:

<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
  <p><input type="text" name="text" value="text default">
  <p><input type="file" name="file1">
  <p><input type="file" name="file2">
  <p><button type="submit">Submit</button>
</form>

Создайте файлы для загрузки:

echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html

Бегать:

nc -l localhost 8000

Откройте HTML-код в браузере, выберите файлы, нажмите «Отправить» и проверьте терминал.

nc печатает полученный запрос. Фаерфокс отправил:

POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:29.0) Gecko/20100101 Firefox/29.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: __atuvc=34%7C7; permanent=0; _gitlab_session=226ad8a0be43681acf38c2fab9497240; __profilin=p%3Dt; request_method=GET
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
Content-Length: 554

-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="text"

text default
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain

Content of a.txt.

-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html

<!DOCTYPE html><title>Content of a.html.</title>

-----------------------------9051914041544843365972754266--

В качестве альтернативы cURL должен отправлять тот же запрос POST, что и ваша форма браузера:

nc -l localhost 8000
curl -F "text=default" -F "[email protected]" -F "[email protected]" localhost:8000

Вы можете выполнить несколько тестов с помощью:

while true; do printf '' | nc -l localhost 8000; done
person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 07.05.2014
comment
Спасибо за отличный пост. Как вы вычисляете длину контента? Является ли длина всего содержимого содержимого (например, только текст по умолчанию) или включая описания (от ---90xx66 до --90xx66--)? - person mojovski; 01.03.2016
comment
@mojovski Я думаю, что это учитывает все, но не уверен на 100%. Попробуйте минимальный пример в своем собственном браузере с этой техникой + wc, чтобы проверить это + попробуйте прочитать стандарт HTTP ;-) Я думаю, что копирование и вставка из переполнения стека + xsel -b | wc не совпадают, потому что серверы отвечают \r\n в конце каждого line, но в какой-то момент они были преобразованы только в \n. Напиши мне, если что-нибудь придумаешь. - person Ciro Santilli 新疆再教育营六四事件ۍ 01.03.2016