Help. Как через PHP передать файл
Мне нужно через PHP с сервера передать файл на другую машину, желательно по частям!
Заранее благодарен.
PS. Если сможете, то скинте какие-нибудь исходники мне на мыло [email]Kasper1985@rambler.ru[/email]
По какому протоколу?
По протоколу TCP/IP. Надо передать через HTTP.
Я выполнил просьбу моего приятеля «RTFM», но мне всё ещё не понятно как это делаеться. В хелпе я прочитал, что нужно при помощи сокетов это делать.
Но у меня проблемы с REQUEST'ом. Я записываю в сокет socket_write($socket, $in, strlen($in));
где $socket — ресурс, а $in — 'Get /XXX\r\nHost: XXX\r\n\r\n';
В результате socket_read(...)выдаёт ошибку...
Может я что-то не то делаю?..:(
socket_write($socket, $in, strlen($in));
где $socket — ресурс, а $in — 'Get /XXX\r\nHost: XXX\r\n\r\n';
Так ты определись: тебе получить файл нужно или отправить?
Выше ты пытаешься его получить методом GET.
Так ты определись: тебе получить файл нужно или отправить?
Выше ты пытаешься его получить методом GET.
Если честно, то и то и другое. GET - это была первая версия, так сказать «сделать хот что нибудь». К стати, я не сказал какая именно ошибка:
Method Not Implemented,
Invalid method in request Get /1/1/car29.MTX HTTP/1.1
Так всё-таки подскажите!!!
Привет! Наверное, я что-то не так объяснил. Вот всё, что есть:
ЗАДАЧА
Клиент запрашивает сценарий на PHP с сервера 1, передаёт в него параметр — имя файла.
Сценарий подключается к серверу 2 и запрашивает с него нужный файл, после чего возвращает его клиенту в отклике вместе с пришедшими заголовками (content-type, content-length и другими).
То есть, получается что-то вроде веб-менеджера закачек, такой себе «байтопровод».
ПРОБЛЕМА
При загрузке файлов по HTTP с сервера 2 и возврате их клиенту в файлах происходят изменения. Например, картинки не выводятся.
Для проверки одновременно с возвратом данных в отклике я записываю их в файл на диске. В файл всё записывается нормально, а в отклике есть какие-то ошибки.
Предположительно, проблема возникает из-за того, что сценарий на PHP не закрывает подключение, и браузер считает, что связь прервалась и данные не догружены.
До того, как стал указывать Content-Length, в конце файла появлялась строчка «Maximum script execution time exceded».
Пробывал добавлять в конец сценария die(), но ничего не меняется.
From Kasper UA
При загрузке файлов по HTTP с сервера 2 и возврате их клиенту в файлах происходят изменения. Например, картинки не выводятся.
From Kasper UA
А что за место картинки путь какой ?
А для чего все это надо ? (ты реализуешь аналог echo file("http:\\что то ");
А что за место картинки путь какой ?
А для чего все это надо ? (ты реализуешь аналог echo file("http:\\что то ");
Получение какртинки идёт через запрос:
GET /бла-бла-бла /HTTP1.1\r\nHOST: бла-бла-бла\r\n...\r\n\r\n.
Я написал раньше это что-то вроде «байтопровода».
Т. е. сценарий берёт большой файл с сервера и по кускам передает клиенту, через промежуточный сервер.
Получение какртинки идёт через запрос:
GET /бла-бла-бла /HTTP1.1\r\nHOST: бла-бла-бла\r\n...\r\n\r\n.
Я написал раньше это что-то вроде «байтопровода».
Т. е. сценарий берёт большой файл с сервера и по кускам передает клиенту, через промежуточный сервер.
А можешь сюда кусок кода закинуть ?
Или прикрепи хочу заценить, а то так тяжело обсуждать.
А можешь сюда кусок кода закинуть ?
Или прикрепи хочу заценить, а то так тяжело обсуждать.
Вот, любуйся:
<?php
//error_reporting (E_ALL);
error_reporting (0);
//header('Content-Type: text/plain');
header('Content-Type: image/jpeg');
$service_port = 80;
$address = '192.168.0.1';
//Создание нового сокета, для отсылани запроса
$socket = socket_create (AF_INET, SOCK_STREAM, getprotobyname("TCP"));
if (!$socket)
{
header('Content-Type: text/html');
die('Creating socket failed:
Reason: '.socket_strerror(socket_last_error($socket)).'
');
}
//Соединение с сервером через созданый сокет
$result = socket_connect ($socket, $address, $service_port);
if (!$result)
{
header('Conten-Type: text/html');
die('Connecting socket failed.
Reason: '.socket_strerror(socket_last_error($socket)).'
');
}
//Передача запроса
$request="GET /1/stone.jpg HTTP/1.1\r\nHost: studio_server\r\n\r\n";
socket_write ($socket, $request, strlen ($request));
/*
Далее я делаю проверку на первое чтение 256 байт,
после чего я определяю длину файла.
По мере скаченого куска файла, яизменяю размер того,
сколько ещё осталось скачать, после чего заканчиваю чтение.
Каждый последующий скаченый кусок я одновременно записываю в
файл и хтмл страницу.
В итоге при просмотре файла всё нормально, а при просмотре
на странице искажёная картинка!!!
*/
$flag=true;
$flag_file=false;
$size=0;
$first=false;
$file=fopen('C:\\file_get.jpg', 'w');
while ($flag)
{
if(!$first)
$out=socket_read($socket, 256, PHP_BINARY_READ);
else
$out=socket_read($socket, 32, PHP_BINARY_READ);
if($flag_file)
{
fwrite($file, $out);
echo $out;
$size-=32;
if($size<=0)
{
$out=socket_read($socket, 64, PHP_BINARY_READ);
fwrite($file, $out);
echo $out;
$flag=false;
}
}
if(!$first&&$pos_begin=strpos($out, 'Content-Length: ')+16)
{
$length=strpos($out, "\n", $pos_begin)-$pos_begin;
$length=substr($out, $pos_begin, $length);
// header('Content-Length: '.$length);
$size=$length-256;
$pos=strpos($out, "\n\r\n")+3;
fwrite($file, substr($out, $pos));
echo substr($out, $pos);
$flag_file=true;
$first=true;
}
if(substr($out, strlen($out)-8)!="\n\r\n0\r\n\r\n"&&!$flag_file)
echo $out;
else if(!$flag_file)
{
echo substr($out, 0, strlen($out)-8);
$flag=false;
}
}
fclose($file);
socket_close ($socket);
//die("\n\r\n0\r\n\r\n");
?>
if(!$first&&$pos_begin=strpos($out, 'Content-Length: ')+16)
особенно это: $pos_begin=strpos($out, 'Content-Length: ')+16 а почему 16 ? и что это вообще ?
заодно и этот иф непонял:
if(substr($out, strlen($out)-8)!="\n\r\n0\r\n\r\n"&&!$flag_file)
если не трудно объясни :)
В «вайле» я предусматриваю вывод списка файлов и передачу самого файла.
Флаг $flag отвечает за конец передачи файла. Как он изменяется, я объясню позже.
Флаг $file_flag устанавливается в true, если передаётся файл. Как это происходит?
В этой самой строке
if(!$first&&$pos_begin=strpos($out, 'Content-Length: ')+16)
я функцией strpos определяю, передаётся ли Content-Length. Если да, то это значит, что передаёться файл. Чтобы определить его длину, а следовательно и количество итераций «вайла» и не вызывать повторно strpos я сразу записываю в $pos_begin позицию начала информации о длине. +16 это необходимое смещение, чтобы не получать 'Content-Length: ххх', а получить номер первого символа длины. После этого я нахожу символ перехода на следующую строку, а значит и конец числа. Таким образом я получаю длину файла, после чего я записываю её в переменную $size.
Флаг $first у меня стоит в положении false только одну итерацию, после чего меняется на true, что позволяет мне единыжды прочитать 256 байт, для того чтобы захватить заголовок, но это только сейчас как черновой вариан, потому что заголовок может меняться как угодно и это не универсальный код.
После я нахожу "\n\r\n", что говорит мне о том что начался сам файл. Далее я начинаю уменьшать $size на количество прочитанных байт и когда значение этой переменной станет меньше либо равно 0, я устанавливаю флаг $flag в положение ложь, что свидетельствует об окончании чтения.
Если же передаётся список файлов, то в заголовке уже не указывается Content-Length, а значит я должен каким либо другим образом фиксировать конец передачи.
При передаче списка файлов, конец передачи передаётся таким набором символов "\n\r\n0\r\n\r\n".
Этим ифом
if(substr($out, strlen($out)-8 )!="\n\r\n0\r\n\r\n"&&!$flag_file)
я, опять таки, пытаюсь фиксировать конец передачи информации, что позволяет мне изменить значение $flag.
После того как я немного усовершенствовал код, т. е. сделал его более понятным и уже менее черновым, то получил новые результаты. Теперь картинка, которую я получаю, отображается нормально в броузере, н при условии, что я её передаю всю целиком и сразу. Вот преобразованный код считывания файла:
$file_begin=false;
$response='';
$header='';
$file_size=0;
do
{
$response.=socket_read($socket, 32, PHP_BINARY_READ);//Считываем по 32 байта
if($pos=strpos($response, "\n\r\n"))//Если закончена передача заголовка
{
$pos+=3;//Смещение на начало данных самого файла
$length_begin=strpos($response, 'Content-Length: ')+16;//Нахождение начала инфы о длине
$length_end=strpos($response, "\n", $length_begin);//Нахождение конца инфы о длине
$length_count=$length_end-$length_begin;//Получение длины строки инфы о размере файла
$length=substr($response, $length_begin, $length_count);//Получение размера файла
$file_size=$length;//Сохранение размера файла в глобальную переменную
$header=substr($response, 0, $pos-3);//Сохранение содержимого заголовка
$response=substr($response, $pos);//Содержимое самого файла
// echo $response; //Вывод содержимого файла на экран
$file_size-=strlen($header);//Подсчет оставшихся байт файла
$file_begin=true;
}
} while(!$file_begin); //Заголовок прочитан и отделён от содержимого файла
while($file_size>0)//Читать пока ещё что-то не прочитано
{
$data=socket_read($socket, 32, PHP_BINARY_READ);//Считываем по 32 байта
$response.=$data;//Записываем как общее содержимое
$file_size-=32;//Подсчет оставшихся байт файла
// echo $data;//Вывод на экран куска файла, размером в 32 байта
}
socket_close ($socket);
echo $response;
Тут помоему всё должно быть понятно!