php post file send
Отдаем файлы эффективно с помощью PHP
1. Используем readfile()
Метод хорош тем, что работает с коробки. Надо только написать свою функцию отправки файла (немного измененный пример из официальной документации):
Таким способом можно отправлять даже большие файлы, так как PHP будет читать файл и сразу отдавать его пользователю по частям. В документации четко сказано, что readfile() не должен создавать проблемы с памятью.
2. Читаем и отправляем файл вручную
Метод использует тот же Drupal при отправке файлов из приватной файловой системы (файлы недоступны напрямую по ссылкам):
3. Используем модуль веб сервера
3a. Apache
Модуль XSendFile позволяет с помощью специального заголовка передать отправку файла самому Apache. Существуют версии по Unix и Windows, под версии 2.0.*, 2.2.* и 2.4.*
В настройках хоста нужно включить перехват заголовка с помощью директивы:
Также можно указать белый список директорий, файлы в которых могут быть обработаны. Важно: если у Вас сервер на базе Windows путь должен включать букву диска в верхнем регистре.
Описание возможных опций на сайте разработчика: https://tn123.org/mod_xsendfile/
Пример отправки файла:
3b. Nginx
Nginx умеет отправлять файлы из коробки через специальный заголовок.
Для корректной работы нужно запретить доступ к папку напрямую через конфигурационный файл:
Пример отправки файла (файл должен находиться в директории /some/path/protected):
Загрузка файлов методом POST
Данная возможность позволяет загружать как текстовые, так и бинарные файлы. С помощью PHP-функций авторизации и манипуляции файлами вы получаете полный контроль над тем, кому разрешено загружать файлы и что должно быть сделано после их загрузки.
PHP способен получать загруженные файлы из любого браузера, совместимого со стандартом RFC-1867.
Замечание: Смежные замечания по конфигурации
Также ознакомьтесь с описанием директив file_uploads, upload_max_filesize, upload_tmp_dir, post_max_size и max_input_time конфигурационного файла php.ini
Пример #1 Форма для загрузки файлов
Страница для загрузки файлов может быть реализована при помощи специальной формы, которая выглядит примерно так:
В приведенном выше примере __URL__ необходимо заменить ссылкой на PHP-скрипт.
Скрытое поле MAX_FILE_SIZE (значение необходимо указывать в байтах) должно предшествовать полю для выбора файла, и его значение является максимально допустимым размером принимаемого файла в PHP. Рекомендуется всегда использовать эту переменную, так как она предотвращает тревожное ожидание пользователей при передаче огромных файлов, только для того, чтобы узнать, что файл слишком большой и передача фактически не состоялась. Помните, обойти это ограничение на стороне браузера достаточно просто, следовательно, вы не должны полагаться на то, что все файлы большего размера будут блокированы при помощи этой возможности. Это по большей части удобная возможность для пользователей клиентской части вашего приложения. Тем не менее, настройки PHP (на сервере) касательно максимального размера обойти невозможно.
Также следует убедиться, что в атрибутах формы вы указали enctype=»multipart/form-data», в противном случае загрузка файлов на сервер выполняться не будет.
Оригинальное имя файла на компьютере клиента.
Mime-тип файла, в случае, если браузер предоставил такую информацию. Пример: «image/gif». Этот mime-тип не проверяется в PHP, так что не полагайтесь на его значение без проверки.
Размер в байтах принятого файла.
Временное имя, с которым принятый файл был сохранен на сервере.
Код ошибки, которая может возникнуть при загрузке файла.
Пример #2 Проверка загружаемых на сервер файлов
По окончанию работы скрипта, в случае, если принятый файл не был переименован или перемещен, он будет автоматически удален из временной папки.
Пример #3 Загрузка массива файлов
PHP поддерживает возможность передачи массива из HTML в том числе и с файлами.
Полоса прогресса загрузки файлов может быть реализована с помощью «отслеживания прогресса загрузки файлов с помощью сессий».
Загрузка файла на сервер без использования формы
Со временем возникла необходимость через формы отсылать еще и файлы. Тогда консорциум W3C взялся за доработку формата POST запроса. К тому времени уже достаточно широко применялся формат MIME (Multipurpose Internet Mail Extensions — многоцелевые расширения протокола для формирования Mail сообщений), поэтому, чтобы не изобретать велосипед заново, решили использовать часть данного формата формирования сообщений для создания POST запросов в протоколе HTTP.
Главное отличие multipart/form-data от application/x-www-form-urlencoded в том, что тело запроса теперь можно поделить на разделы, которые разделяются границами. Каждый раздел может иметь свой собственный заголовок для описания данных, которые в нем хранятся, т.е. в одном запросе можно передавать данные различных типов (как в теле письма можно одновременно с текстом передавать файлы). Пример запроса:
Boundary (граница) — это последовательность байтов, которая не должна встречаться внутри передаваемых данных. Content-Length — суммарный объём, включая дочерние заголовки. Само содержимое полей при этом оставляется «как есть».
CURL, multipart/form-data
Файл get.php на сервере http://server.com:
Важный момент: на форуме PHPCLUB.RU встретил упоминание, что может потребоваться указание полного пути файла — иначе CURL выдает ошибку.
CURL, application/x-www-form-urlencoded
Файл get.php на сервере http://server.com:
Сокеты, multipart/form-data
Файл get.php на сервере http://server.com:
Сокеты, application/x-www-form-urlencoded
Файл get.php на сервере http://server.com:
Метод PUT
Описанные выше способы работают для относительно небольших файлов (примерно до 2-х мегабайт, для получения более точного значения необходимо смотреть в настройках PHP максимальный объем принимаемых данных методом POST). Чтобы обойти это ограничение, будем передавать файл методом PUT:
POST запрос, составное содержимое (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 не подходит, то данную библиотеку можно применить и для отправки через сокеты. Ну и собственно ссылки на источники:
How do I send a POST request with PHP?
Actually I want to read the contents that come after the search query, when it is done. The problem is that the URL only accepts POST methods, and it does not take any action with GET method.
16 Answers 16
CURL-less method with PHP5:
See the PHP manual for more information on the method and how to add headers, for example:
@Edward mentions that http_build_query may be omitted since curl will correctly encode array passed to CURLOPT_POSTFIELDS parameter, but be advised that in this case the data will be encoded using multipart/form-data.
I use this function with APIs that expect data to be encoded using application/x-www-form-urlencoded. That’s why I use http_build_query().
I recommend you to use the open-source package guzzle that is fully unit tested and uses the latest coding practices.
Installing Guzzle
Go to the command line in your project folder and type in the following command (assuming you already have the package manager composer installed). If you need help how to install Composer, you should have a look here.
Using Guzzle to send a POST request
The usage of Guzzle is very straight forward as it uses a light-weight object-oriented API:
I’d like to add some thoughts about the curl-based answer of Fred Tanrikut. I know most of them are already written in the answers above, but I think it is a good idea to show an answer that includes all of them together.
Here is the class I wrote to make HTTP-GET/POST/PUT/DELETE requests based on curl, concerning just about the response body:
Improvements
Example of usage
DELETE
Testing
You can also make some cool service tests by using this simple class.
There’s another CURL method if you are going that way.