- Загрузка файла на сервер без использования формы
- CURL, multipart/form-data
- CURL, application/x-www-form-urlencoded
- Сокеты, multipart/form-data
- Сокеты, application/x-www-form-urlencoded
- Метод PUT
- Отправка данных из скрипта методом POST
- Отправка данных методом POST через сокеты
- Отправка данных методом POST с использованием CURL
Загрузка файла на сервер без использования формы
Для 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] => Какое-то сообщение от пользователя )
Отправка данных из скрипта методом POST
HTML форма позволяет пользователю сформировать POST-запрос, который затем отсылается браузером. Мы сформируем такой запрос скриптом. Пусть у нас есть простая форма, состоящая из двух полей и кнопки для отправки данных:
action="/handler/action.php" method="post"> Имя: name="name" type="text" />
Пароль: name="password" type="password" />
name="submit" type="submit" value="Отправить" />
Обработчик формы action.php выводит в браузер текст, введенный в поля формы:
echo 'Имя: '.$_POST['name'].'
'; echo 'Пароль: '.$_POST['password'].'
';
Метод POST, в отличие от метода GET, посылает данные не в строке запроса, а в области данных, после заголовков. Передача данных аналогична методу GET: группы name=value объединяются при помощи амперсанда (&):
name=Евгений&password=qwerty
Кроме того, необходимо учитывать, что данные передаются в текстовом виде, поэтому все национальные символы следует подвергать кодированию при помощи функции urlencode() .
Отправка данных методом POST через сокеты
$hostname = 'localhost'; $path = '/handler/action.php'; $content = ''; // Устанавливаем соединение с сервером $hostname $fp = fsockopen($hostname, 80, $errno, $errstr, 30); // Проверяем успешность установки соединения if (!$fp) die(''
.$errstr.' ('.$errno.')'); // Данные HTTP-запроса $data = 'name='.urlencode('Евгений').'&password='.urlencode('qwerty'); // Заголовок HTTP-запроса $headers = 'POST '.$path." HTTP/1.1\r\n"; $headers .= 'Host: '.$hostname."\r\n"; $headers .= "Content-type: application/x-www-form-urlencoded\r\n"; $headers .= 'Content-Length: '.strlen($data)."\r\n\r\n"; // Отправляем HTTP-запрос серверу fwrite($fp, $headers.$data); // Получаем ответ while ( !feof($fp) ) $content .= fgets($fp, 1024); // Закрываем соединение fclose($fp); // Выводим ответ в браузер echo $content;
Результат работы скрипта выглядит примерно так
HTTP/1.1 200 OK Date: Sat, 28 Jun 2008 07:53:19 GMT Server: Apache/2.0.55 (Win32) PHP/5.2.1 X-Powered-By: PHP/5.2.1 Content-Length: 42 Content-Type: text/html Имя - Евгений
Пароль - qwerty
Отправка данных методом POST с использованием CURL
Помимо сокетов, обеспечивающих низкоуровневое обращение к серверу, PHP располагает специальным расширением CURL (Client URL Library).
// Задаем адрес удаленного сервера $curl = curl_init("http://localhost/handler/action.php"); // Передача данных осуществляется методом POST curl_setopt($curl, CURLOPT_POST, 1); // Задаем POST-данные $data = 'name=Евгений&password=qwerty'; curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Выполняем запрос и выводим ответ в браузер curl_exec($curl); // Закрываем CURL соединение curl_close($curl);
С помощью функции curl_init() задается адрес удаленного сервера и путь к файлу на нем. В отличие от функции fsockopen() , необходимо задавать адрес полностью, включая префикс http:// , т.е. расширение CURL позволяет работать с несколькими видами протоколов (HTTP, HTTPS, FTP). Если соединение с указанным сервером происходит успешно, функция curl_init() возвращает дескриптор соединения, который используется во всех остальных функциях библиотеки.
Для того, чтобы сообщить CURL о том, что данные будут передаваться методом POST, необходимо задать параметр CURLOPT_POST . POST-данные устанавливаются при помощи параметра CURLOPT_POSTFIELDS .
По умолчанию библиотека удаляет HTTP-заголовки, возвращаемые сервером. Однако CURL можно настроить на выдачу заголовков, если установить при помощи функции curl_setopt() ненулевое значение параметра CURLOPT_HEADER .
P.S. Из-за ошибки библиотеки сокетов протокол HTTP 1.1 под Windows работает медленно. При работе скрипта использующего сокеты под управлением этой ОС, лучше использовать версию HTTP 1.0.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
- 1С:Предприятие (31)
- API (29)
- Bash (43)
- CLI (99)
- CMS (139)
- CSS (50)
- Frontend (75)
- HTML (66)
- JavaScript (150)
- Laravel (72)
- Linux (146)
- MySQL (76)
- PHP (125)
- React.js (66)
- SSH (27)
- Ubuntu (68)
- Web-разработка (509)
- WordPress (73)
- Yii2 (69)
- БазаДанных (95)
- Битрикс (66)
- Блог (29)
- Верстка (43)
- ИнтернетМагаз… (84)
- КаталогТоваров (87)
- Класс (30)
- Клиент (27)
- Ключ (28)
- Команда (68)
- Компонент (60)
- Конфигурация (62)
- Корзина (32)
- ЛокальнаяСеть (28)
- Модуль (34)
- Навигация (31)
- Настройка (140)
- ПанельУправле… (29)
- Плагин (33)
- Пользователь (26)
- Практика (99)
- Сервер (74)
- Событие (27)
- Теория (105)
- Установка (66)
- Файл (47)
- Форма (58)
- Фреймворк (192)
- Функция (36)
- ШаблонСайта (68)