Chunked transfer средствами CURL как рализовать

A4
На сайте с 05.01.2012
Offline
55
3937

В общем то это задача не такая уж и сложная. Я решил ее вот так:


header("Transfer-Encoding: chunked");
header("Connection: close");
header('Content-Disposition: filename=123.file');
$download_rate = 500;//размер чанка
set_time_limit(45);//а куда же без этого....((
flush();
$file = fopen($file_url, "rb");
while(!feof($file)){
print fgets($file, round($download_rate * 1024));
flush();//очищаем выходной поток, таким образом закончив передачу чанка.
}
fclose($file);

Это превосходно работает. Но! хотелось бы чтобы было лучше. Во первых fopen не очень хороший способ скачки файла ибо user-agent не подменить это раз. Во вторых Range не указать, ну то есть откуда покуда качать(какую часть файла). В CURL это делается директивой CURLOPT_RANGE.

Да я знаю о функции fseek, но если файл находится на удаленном хосте - то эта функция нифига не пашет как надо. Зато CURLOPT_RANGE пашет, я проверял).

Собственно меня интересует как реализовать передачу файла по чанкам через CURL. Пока что это делается так:


$hdr = array("Range: bytes=".$position."-".($position + $size));
$ch = curl_init($file_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $hdr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0");
$data = curl_exec($ch);
curl_close($ch);
echo $data;

Это не очень хороший вариант, так как пока скрипт не считает удаленный файл в оперативу - он отдавать его не начнет. То есть придется ждать минуты 4 пока файл буферизуется! В 1 случае эта проблемма решается через flush() - эта команда вынуждает данные выводиться из буфера. Но вот куда мне командку flush в CURL'е поставить я ума не приложу. Где-то читал про CURLOPT_WRITEFUNCTION, но как с ней работать и то ли это что я ищу - не знаю. Знающие люди - помогите разобраться что к чему.

siv1987
На сайте с 02.04.2009
Offline
427
#1
aftamat4ik:
Это не очень хороший вариант, так как пока скрипт не считает удаленный файл в оперативу - он отдавать его не начнет.

Конечно не отдает, если там установлена опция CURLOPT_RETURNTRANSFER. По моему даже с вами мы это уже один раз обсуждали.

ПС.

А через fopen агент и заголовки можно передать http://php.net/manual/ru/function.fopen.php

A4
На сайте с 05.01.2012
Offline
55
#2
siv1987:
По моему даже с вами мы это уже один раз обсуждалось.

Да да, обсуждалось. К несчастью я тогда нашел 1 вариант скачки файла через fopen и просто напросто на curl забил. Сейчас решил что поступил не совсем верно. Ок, ща выпилю эту опцию.

---------- Добавлено 09.05.2013 в 17:26 ----------

Было сделано так:


header("Transfer-Encoding: chunked");
header('Content-Disposition: filename='.$tmp_name.'.mp3');
$ch = curl_init($file_url);

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_REFERER, "http://vk.com/swf/audio_lite.swf?_stV=10");
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0");
curl_setopt($ch, CURLOPT_BUFFERSIZE, 512000); //в байтах

$data = curl_exec($ch);
curl_close($ch);
echo $data;

Он так вообще не качает(

---------- Добавлено 09.05.2013 в 17:50 ----------


$com = "GET $file HTTP/1.1\r\nAccept: */*\r\nAccept-Language: de-ch\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\nHost: $server:$port\r\nConnection: Keep-Alive\r\n\r\n";
fputs($fp, $com);
siv1987:
А через fopen агент и заголовки можно передать http://php.net/manual/ru/function.fopen.php

Круто!) Только что заметил0 Спасибо)

siv1987
На сайте с 02.04.2009
Offline
427
#3
aftamat4ik:
Он так вообще не качает(

Должен. Но раз результат отдается сразу, то

curl_exec($ch);

curl_close($ch);

Смотрите что-бы были все необходимые заголовки

CURLOPT_BUFFERSIZE

WTF?

Для аттачей заголовок по моему должен быть таким

header('Content-Disposition: attachment;filename='.$tmp_name.'.mp3');

siv1987
На сайте с 02.04.2009
Offline
427
#4
aftamat4ik:
Он так вообще не качает(

А если вообще не качает, тогда вообще удалите header("Transfer-Encoding: chunked");

так как апач сам будет отдавать этого заголовок если Content-length не известен, и кодировать пакет в соответствий с форматом Chunked transfer

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий