Php передача файлов post запросом
Чтобы загрузить файл на сервер, нам надо использовать форму с параметром enctype=»multipart/form-data» и массив $_FILES . Итак, создадим файл upload.php со следующим содержимым:
?>Загрузка файла
Здесь определена форм с атрибутом enctype=»multipart/form-data» . Форма содержит специальное поле для выбора файла.
Все загружаемые файлы попадают в ассоциативный массив $_FILES . Чтобы определить, а есть ли вообще загруженные файлы, можно использовать конструкцию if: if ($_FILES)
Массив $_FILES является двухмерным. Мы можем загрузить набор файлов, и каждый загруженный файл можно получить по ключу, который совпадает со значением атрибута name .
Так как элемент для загрузки файла на форме имеет name=»filename» , то данный файл мы можем получить с помощью выражения $_FILES[«filename»] .
У каждого объекта файла есть свои параметры, которые мы можем получить:
- $_FILES[«file»][«name»] : имя файла
- $_FILES[«file»][«type»] : тип содержимого файла, например, image/jpeg
- $_FILES[«file»][«size»] : размер файла в байтах
- $_FILES[«file»][«tmp_name»] : имя временного файла, сохраненного на сервере
- $_FILES[«file»][«error»] : код ошибки при загрузке
Также мы можем проверить наличие ошибок при загрузке. Если у нас нет ошибки, то поле $_FILES[«filename»][«error»] содержит значение UPLOAD_ERR_OK .
При отправке файла на сервер он сначала загружается во временное место, из которого затем с помощью функции move_uploaded_file() он перемещается в каталог сервера, где расположен скрипт «upload.php».
Также мы можем указать другой путь, например, допустим, на сервере есть папка «upload», тогда, чтобы загружать в нее файлы, необходимо указать соответствующий путь:
if ($_FILES && $_FILES["filename"]["error"]== UPLOAD_ERR_OK) < $name = "upload/" . $_FILES["filename"]["name"]; move_uploaded_file($_FILES["filename"]["tmp_name"], $name); echo "Файл загружен"; >
Функция move_uploaded_file() принимает два параметра путь к загруженному временному файлу и путь, куда надо поместить загруженный файл.
Ограничения и настройка загрузки
По умолчанию размер загружаемых файлов ограничен 2 мб. Однако можно настроить данный показатель в файле конфигурации. Изменим этот показатель, например, до 10 мб. Для этого найдем в файле php.ini следующую строку:
Также мы можем настроить папку для временных загружаемых файлов. Для этого в файле php.ini найдем следующую строку:
upload_tmp_dir = "C:/php/upload"
Также в каталоге php нам надо создать папку upload .
Мультизагрузка
Изменим скрипт upload.php так, чтобы он поддерживал множественную загрузку:
$error) < if ($error == UPLOAD_ERR_OK) < $tmp_name = $_FILES["uploads"]["tmp_name"][$key]; $name = $_FILES["uploads"]["name"][$key]; move_uploaded_file($tmp_name, "$name"); >> echo "Файлы загружены"; > ?>Загрузка файла
Каждое поле выбора файла имеет атрибут name=»uploads[]» , поэтому сервер будет рассматривать набор отправленных файлов как единый массив.
Затем используя цикл foreach , проходим по все файлам и сохраняем их в каталог веб-сайта.
Загрузка файла на сервер без использования формы
Для HTTP запроса типа POST существует два варианта передачи полей из HTML форм, а именно, используя алгоритм application/x-www-form-urlencoded и multipart/form-data . Алгоритм первого типа создавался давным-давно, когда в языке HTML еще не предусматривали возможность передачи файлов через HTML формы.
Со временем возникла необходимость через формы отсылать еще и файлы. Тогда консорциум W3C взялся за доработку формата POST запроса. К тому времени уже достаточно широко применялся формат MIME (Multipurpose Internet Mail Extensions — многоцелевые расширения протокола для формирования Mail сообщений), поэтому, чтобы не изобретать велосипед заново, решили использовать часть данного формата формирования сообщений для создания POST запросов в протоколе HTTP.
Главное отличие multipart/form-data от application/x-www-form-urlencoded в том, что тело запроса теперь можно поделить на разделы, которые разделяются границами. Каждый раздел может иметь свой собственный заголовок для описания данных, которые в нем хранятся, т.е. в одном запросе можно передавать данные различных типов (как в теле письма можно одновременно с текстом передавать файлы). Пример запроса:
Content-Type: multipart/form-data; boundary=ff4ed67396bc8e1d6dbf19d65b6c6348 Content-Length: 417339 --ff4ed67396bc8e1d6dbf19d65b6c6348 Content-Disposition: form-data; name="name" Евгений --ff4ed67396bc8e1d6dbf19d65b6c6348 Content-Disposition: form-data; name="message" Какое-то сообщение от пользователя --ff4ed67396bc8e1d6dbf19d65b6c6348 Content-Disposition: form-data; name="upload"; filename="image.jpg" Content-Type: image/jpeg Content-Transfer-Encoding: binary . содержимое файла image.jpg. --ff4ed67396bc8e1d6dbf19d65b6c6348--
Boundary (граница) — это последовательность байтов, которая не должна встречаться внутри передаваемых данных. Content-Length — суммарный объём, включая дочерние заголовки. Само содержимое полей при этом оставляется «как есть».
CURL, multipart/form-data
$file = 'image.jpg'; $postdata = array( 'name' => 'Евгений', 'message' => 'Какое-то сообщение от пользователя', 'upload' => '@'.$file ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://server.com/get.php'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_exec($ch); curl_close($ch);
Файл get.php на сервере http://server.com:
print_r($_POST); print_r($_FILES); move_uploaded_file($_FILES['upload']['tmp_name'], 'image.jpg');
Array ( [name] => Евгений [message] => Какое-то сообщение от пользователя ) Array ( [upload] => Array ( [name] => image.jpg [type] => application/octet-stream [tmp_name] => C:\Windows\Temp\php504D.tmp [error] => 0 [size] => 416919 ) )
Важный момент: на форуме PHPCLUB.RU встретил упоминание, что может потребоваться указание полного пути файла — иначе CURL выдает ошибку.
$file = 'C:/work/localhost/www/image.jpg';
CURL, application/x-www-form-urlencoded
$file = 'image.jpg'; // данные POST-запроса $postdata = array( 'name' => 'Евгений', 'message' => 'Какое-то сообщение от пользователя', 'upload' => file_get_contents($file) ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://server.com/get.php'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_exec($ch); curl_close($ch);
Файл get.php на сервере http://server.com:
print_r($_POST); file_put_contents('image.jpg', $_POST['upload']);
Array ( [name] => Евгений [message] => Какое-то сообщение от пользователя [upload] => . содержимое файла image.jpg. )
Сокеты, multipart/form-data
// устанавливаем соединение с сервером $fp = fsockopen('server.com', 80, $errno, $errstr, 30); if (!$fp) die($errstr.' ('.$errno.')'); $name = 'Евгений'; $message = 'Какое-то сообщение от пользователя'; $file = 'image.jpg'; // содержимое файла $content = file_get_contents($file); // разделитель $boundary = md5(uniqid(time())); $body = '--'.$boundary."\r\n"; $body = $body.'Content-Disposition: form-data; name="name"'."\r\n\r\n"; $body = $body.$name."\r\n"; $body = $body.'--'.$boundary."\r\n"; $body = $body.'Content-Disposition: form-data; name="message"'."\r\n\r\n"; $body = $body.$message."\r\n"; $body = $body.'--'.$boundary."\r\n"; $body = $body.'Content-Disposition: form-data; name="upload"; filename="image.jpg"'."\r\n"; $body = $body.'Content-Type: image/jpeg'."\r\n"; $body = $body.'Content-Transfer-Encoding: binary'."\r\n\r\n"; $body = $body.$content."\r\n"; $body = $body.'--'.$boundary.'--'; // пишем в сокет метод, URI и протокол fwrite($fp, 'POST /get.php HTTP/1.1'."\r\n"); // а также имя хоста fwrite($fp, 'Host: server.com'."\r\n"); // отправляем заголовки fwrite($fp, 'Content-Type: multipart/form-data; boundary='.$boundary."\r\n"); fwrite($fp, 'Content-Length: '.strlen($body)."\r\n\r\n"); // теперь передаем данные fwrite($fp, $body); // получаем ответ $result = ''; while ( !feof($fp) ) $result .= fgets($fp, 1024); // закрываем соединение fclose($fp); // выводим ответ в браузер echo $result;
Файл get.php на сервере http://server.com:
print_r( $_POST ); print_r( $_FILES ); move_uploaded_file($_FILES['upload']['tmp_name'], 'image.jpg')
HTTP/1.1 200 OK Server: Apache/2.0 (Win32) PHP/5.1 X-Powered-By: PHP/5.1 Content-Length: 310 Array ( [name] => Евгений [message] => Какое-то сообщение от пользователя ) Array ( [upload] => Array ( [name] => image.jpg [type] => image/jpeg [tmp_name] => C:\Windows\Temp\phpA457.tmp [error] => 0 [size] => 416919 ) )
Сокеты, application/x-www-form-urlencoded
// устанавливаем соединение с сервером $fp = fsockopen('server.com', 80, $errno, $errstr, 30); if (!$fp) die($errstr.' ('.$errno.')'); $file = 'image.jpg'; // содержимое файла $content = file_get_contents($file); // данные POST-запроса $data = 'name=' . urlencode('Евгений') . '&message=' . urlencode('Какое-то сообщение от пользователя') . '&upload='.urlencode($content); // заголовоки запроса $headers = 'POST /get.php HTTP/1.1'."\r\n"; $headers .= 'Host: server.com'."\r\n"; $headers .= 'Content-type: application/x-www-form-urlencoded'."\r\n"; $headers .= 'Content-Length: '.strlen($data)."\r\n\r\n"; // отправляем запрос серверу fwrite($fp, $headers.$data); // получаем ответ $result = ''; while ( !feof($fp) ) $result .= fgets($fp, 1024); // закрываем соединение fclose($fp); // выводим ответ в браузер echo $result;
Файл get.php на сервере http://server.com:
print_r($_POST); file_put_contents('image.jpg', $_POST['upload']);
HTTP/1.1 200 OK Server: Apache/2.0 (Win32) PHP/5.1 X-Powered-By: PHP/5.1 Transfer-Encoding: chunked Array ( [name] => Евгений [message] => Какое-то сообщение от пользователя [upload] => . содержимое файла image.jpg. )
Метод PUT
Описанные выше способы работают для относительно небольших файлов (примерно до 2-х мегабайт, для получения более точного значения необходимо смотреть в настройках PHP максимальный объем принимаемых данных методом POST). Чтобы обойти это ограничение, будем передавать файл методом PUT:
$url = 'http://server.com/get.php'; $file = 'image.jpg'; // Открываем передаваемый файл на чтение для дальнейшей его передачи $fp = fopen($file, 'r'); // Инициализируем сеанс CURL $ch = curl_init(); // Указываем URL скрипта, который примет наш запрос. К имени скрипта // добавляем еще две переменные, передаваемые методом GET curl_setopt($ch, CURLOPT_URL, $url . '?name=' . urlencode('Евгений') . '&message=' . urlencode('Какое-то сообщение от пользователя')); // Дескриптор файла, который собираемся передать curl_setopt($ch, CURLOPT_INFILE, $fp); // Указываем размер отправляемого файла curl_setopt($ch, CURLOPT_INFILESIZE, filesize($file)); // Указываем, что файл передается методом PUT curl_setopt($ch, CURLOPT_PUT, 1); // Указываем, что будет производиться закачка на удаленный сервер curl_setopt($ch, CURLOPT_UPLOAD, 1); // Выполняем запрос CURL curl_exec($ch); // Завершаем сеанс CURL curl_close($ch);
Файл get.php на сервере http://server.com:
print_r($_GET); file_put_contents ('image.jpg', file_get_contents('php://input'));
Array ( [name] => Евгений [message] => Какое-то сообщение от пользователя )