Отправка файла методом PUT

Как уже говорилось, отправка файлов на удаленный сервер методом POST через сокеты хороша для файлов маленьких размеров. Для передачи файлов больших размеров лучше применить передачу методом PUT. Для этого воспользуемся библиотекой curl. Для передачи файла методом PUT нам необходимо инициализировать сеанс CURL, задать необходимые параметры, выполнить запрос CURL и закрыть сеанс.

Следующий пример демонстрирует передачу файла file.zip серверу B:

// Задаем скрипт на сайте B, который примет наш запрос и обработает его
$url = 'http://serverB/import.php';

// Указываем файл, который мы хотим передать сайту B
// Если файл находится не в текущей дирректории, то необходимо
// указать путь до файла
$file = 'file.zip';

// Узнаем размер передаваемого файла
$filesize = filesize($file);

// Узнаем имя файла (в случае, если в $file указан полный путь до файла)
$pathinfo = pathinfo($file);
$filename = $pathinfo['basename'];

// Открываем передаваемый файл на чтение
// для дальнейшей его передачи
$fp = fopen($file, 'r');

// Инициализируем сеанс CURL
$ch = curl_init();

// Задаем параметры для открытого сеанса CURL

// Указываем URL скрипта, который примет наш запрос
// К имени скрипта добавляем переменную, содержащую имя передаваемого файла
// Чтобы это имя было доступно в принимающем скрипте из массива $_GET
curl_setopt($ch, CURLOPT_URL, $url . '?filename=' . $filename);

// Указываем файл (а вернее дескриптор открытого на чтение файла), 
// который собираемся передать
curl_setopt($ch, CURLOPT_INFILE, $fp);

// Указываем предполагаемый размер отправляемого файла
curl_setopt($ch, CURLOPT_INFILESIZE, $filesize);

// Указываем, что файл передается методом PUT
curl_setopt($ch, CURLOPT_PUT, true);

// Указываем, что будет производиться закачка на удаленный сервер
curl_setopt($ch, CURLOPT_UPLOAD, true);

// Выполняем запрос CURL
curl_exec($ch);

// Завершаем сеанс CURL
curl_close($ch);

После выполнения этого сценария с сайта A на сайт B уйдет PUT-запрос, в котором будет находиться содержимое передаваемого файла, а в GET-запросе будет содержаться название передаваемого файла.

Далее нам необходимо организовать прием файла на сайте B. Для этого в скрипте import.php, находящегося на сайте B, из массива $_GET мы должны получить название файла, а из входного потока – содержимое файла:

// Определяем имя файла
// Если не определено, задаем как unknow.dat
$filename = (isset($_GET['filename'])) ? $_GET['filename'] : 'unknow.dat';

// Получаем содержимое входящего потока
$content = file_get_contents('php://input');

// Записываем содержимое потока в файл
$file = fopen($filename, 'w+');
fwrite($file, $content);
fclose($file);

Таким методом можно передавать файлы больших объемов.

Стоит также упомянуть, что приведенные выше два способа передачи файлов не являются единственно возможными способами. Например, можно передавать файлы из PHP-скриптов на удаленные сервера по FTP-протоколу (используя тот же CURL или специальные функции PHP, такие как ftp_connect(), ftp_login(), ftp_put() и т.д.). Но ведь доступ к сайту по FTP может быть затруднен (не известны имя пользователя и пароль, или они были изменены на сервере, но не изменены в скриптах и т.д.). А указанный здесь способ будет корректно работать на любых типах хостинга.

Также обращаю ваше внимание, что указанные здесь методики освещают возможность загрузки файлов на сервер. Использование их "в чистом виде" без доработки может быть небезопасным, и является потенциальной возможностью для взлома вашего сайта. А именно, отсутствие обработки имени файла, который пришел на сайт B, отсутствие авторизации, определения сайта, посылающего файл, может дать злоумышленнику возможность загрузить и выполнить вредоносный код на вашем сайте. Рассмотрение способов защиты не входит в данную статью и остается на ваше усмотрение.


.