curl multipart form data

Передача составных данных методом POST

В жизни любого программиста попадаются задачки, которые человека цепляют. Вот не нравится стандартный метод решения и все! А порой бывает, что стандартные решения не подходят по какой-то причине. Некоторые люди обходят такие задачи стороной, другие же любят решать их. Можно даже сказать сами их находят. Одна из таких задач отсылка файла или несколько файлов методом POST.

Некоторые наверное скажут, эта задача совсем не задача. Ведь есть замечательная библиотека CURL, которая довольно простая и решает эту задачу легко! Но не спешите. Да, CURL мощная библиотека, да она загружает файлы, но… Как Вы знаете у нее есть маленькая особенность — файл должен быть размещен на жестком диске!

А теперь давайте представим себе такую ситуацию, Вы генерируете динамически файл или же он уже находится в памяти и нужно его отправить методом POST на удаленный Web сервер. Что же тогда получается? Перед его отправкой нужно его сохранить? Да именно так и поступило бы 90% программистов. Зачем искать лишние проблемы, если решение лежит на поверхности? Но мы же с Вами не из этих 90%! Мы же лучше, мы же можем решить любую задачку. Зачем нам лишнее действие? Во-первых, оно задействует не быструю файловую систему жесткого диска. Во-вторых, у нас может и не быть доступа к файловой системе или же там выделено слишком мало места.

Как же нам тогда решить эту задачку? Для этого надо взглянуть как собственно передаются данные методом POST. Единственный вариант решения — это передача файла составным запросом с помощью multipart/form-data. Этот метод хорошо описан в RFC7578. Давайте взглянем как будет выглядеть тело POST запроса multipart/form-data:

Наше тело состоит из двух частей, в первой части мы передаем значение поля формы name=«field» равное: text. Во второй части мы передаем поле name=«file» с содержимым файла filename=«sample.txt»: Content file. В заголовке мы указываем формат содержимого POST запроса — Content-Type: multipart/form-data, строку разделитель составных частей: boundary=————-573cf973d5228 и длину сообщения — Content-Length: 288.

Осталось, собственно, написать программу реализующий этот метод. Так как мы люди умные и не пишем по сто раз одно и тоже в разных проектах, то оформим все в виде класса реализующий этот метод. Плюс к этому, расширим его для разных вариантов отправки как файлов, так и простых элементов формы. А что бы отличить среди массива POST данных, наличие файла, создадим отдельный файл — контейнер с содержимым файла и его данных (имя и расширение). Таким образом он будет выглядеть следующим образом:

Теперь собственно сам класс по формированию тела multipart/form-data для POST запроса:

Данный класс состоит из нескольких методов. Метод — PartPost формирует отдельные части составного запроса, а метод — Get объединяет эти части и формирует тело POST запроса в формате — multipart/form-data.

Теперь у нас есть универсальный класс для отправки тела POST запроса. Осталось написать программу использующую данный класс для отправки файлов на удаленный Web сервер. Воспользуемся библиотекой CURL:

Если CURL не подходит, то данную библиотеку можно применить и для отправки через сокеты. Ну и собственно ссылки на источники:

  • сайт документации php.net
  • статья CURL: POST запрос, составное содержимое
  • википендия: multipart/form-data
  • RFC7578

В следующей статье предложу вашему вниманию информацию о том, как качать большие файлы с удаленных Web-серверов в несколько потоков, с указанной скоростью. Всем, кто дочитал до конца, спасибо за внимание!

Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.

Many answers yet on this topic on this website, but none helps me.

I am trying to post a file to box (cloud storage). Should be easy but it is not.

I use RequestBin to debug.

When using curl on commandline, it works great (file is posted to Box) :

When trying to do the same (upload a file to Box) with php curl it fails (with no response at all, which means no file content could be found).

I also see on RequestBin that my POST looks different.

Curl cli (correct) :

——————————cd86e864290b Content-Disposition: form-data; name=»attributes»

Curl php (not correct) :

——————————7ab3fffab8c6 Content-Disposition: form-data; name=»attributes»

This is cleary not the same and I don’t know how to get the same result.

I just don’t seem to get the correct format for the file I want to post.

1 Answer 1

you’re looking for CURLFile.

also, when using multipart/form-data or application/x-www-urlencoded encoding, don’t set the content-type header manually, curl will set the appropriate header for you automatically, and unlike you, curl won’t make any typos in doing so.

also, curl_setopt_array returns bool(false) if there was a problem setting your options, and you should not ignore those errors, thus i recommend using this function instead, it converts any curl setopt errors to a RuntimeException

and a protip, when debugging curl code, enable CURLOPT_VERBOSE.

Здравствуйте. Уже весь день пытаюсь сделать но не идет ни как. В телеграмм(https://telegram.org) пишу бота. И там фотографию принимает API только как «multipart/form-data» а нужно отправить фото которое по адресу
http://i.imgur.com/ea9PB3H.png
писал:

Может подскажете рабочий вариант?
PS. Отправка через форму

работает отлично
UPD
тоже не работает
ошибка

Оцените статью