Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Сеть > вывод файла php скриптом, с поддержкой докачки


Автор: xamloru 2.8.2007, 13:40
Мне необходимо чтобы любой downloader с поддержкой докачки файлов, мог докачивать с моего скрипта.
Редирект (аля Location: URL) не подхоит.
вот код моего скрипта:
Код

<?
$headers = getallheaders();
$headout = "";
$pref="";
function put_log($str){
    $fp=fopen("log.txt",'a');
    fwrite($fp,"$str\n");
    fclose($fp);
}
while (list ($header, $value) = each ($headers)) {
    $headout.="$header: $value\n";
    if(strpos($header,"Range")!==false){
     $pref="cc_";
     $str=substr($value,strpos($value,"=")+1);
     $range=explode('-',$str);
     $range[0]=intval($range[0]);
     $range[1]=intval($range[1]);
    }
}
$f=fopen($pref."headers.txt",'w');
fwrite($f,$headout);
fclose($f);
$filename="YandexDesktopSetup.exe";
header("Content-Type: application/octet-stream");
header("Last-Modified: ".gmdate('D, d M Y H:i:s', (1186041494)).' GMT');
header('ETag: "0-46435e-469c68a3"');
header("Accept-Ranges: bytes");
if(isset($range)){
    header("Content-Range: bytes {$range[0]}-{$range[1]}/".filesize($filename));
    $length=$range[1]-$range[0]+1;
    put_log("Content-Range: bytes {$range[0]}-{$range[1]}/".filesize($filename));
}
header("Content-Disposition: attachment; filename=\"Ya.exe\"");
if(isset($length)){
    header("Content-Length: ".$length);
    put_log("len: $length");
}else {
    header("Content-Length: ".filesize($filename));
}
$f=fopen($filename,'rb');
if(isset($range)){
    fseek($f,$range[0]);
}
while (!feof($f)) {
    $cont=fread($f,1);
    echo $cont;
}
fclose($f);
?>


при тестирование не забудьте поменять имя файла $filename="YandexDesktopSetup.exe";
Я пользуюсь DownThemAll
он не видет поддержку докачки.
очень странно, вроде сделал все по стандарту HTTP как там написанно было
плиз помогите, может еще какой заголовок нужен.

Автор: xamloru 3.8.2007, 10:49
Значит так, я разобрался почему не работало, теперь оно работает, но конечно не со 100 % гарантией.
Решение было следующее:

не во всех случаях range вычислялся правильно.
правильный код:
Код

$str=substr($value,strpos($value,"=")+1);
$range=explode('-',$str);
if($range[0]==''){
     $range[0]=filesize($filename)-intval($range[1])-1;
     $range[1]=filesize($filename)-1;
}else{
     $range[0]=intval($range[0]);
     $range[1]=($range[1]=='')?filesize($filename)-1:intval($range[1]);
 }


некоторым давнлоадерам необходимы хеадеры со статусом partial content.
в итоге код полностью будет выглядеть так:
Код

<?
$headers = getallheaders();
$headout = "";
$pref="";
$filename="Flash8-en.exe";
function put_log($str){
    $fp=fopen("log.txt",'a');
    fwrite($fp,"$str\n");
    fclose($fp);
}
while (list ($header, $value) = each ($headers)) {
    $headout.="$header: $value\n";
    if(strpos($header,"Range")!==false){
     $pref="cc_";
     $str=substr($value,strpos($value,"=")+1);
     $range=explode('-',$str);
     if($range[0]==''){
         $range[0]=filesize($filename)-intval($range[1])-1;
         $range[1]=filesize($filename)-1;
     }else{
     $range[0]=intval($range[0]);
     $range[1]=($range[1]=='')?filesize($filename)-1:intval($range[1]);
     }
     put_log("Range: $value");
    }
}
$f=fopen($pref."headers.txt",'w');
fwrite($f,$headout);
fclose($f);
header("Content-Type: application/octet-stream");
header("Last-Modified: ".gmdate('D, d M Y H:i:s', (1186041494)).' GMT');
header('ETag: "0-46435e-469c68a3"');
if(isset($range)){
    //header("Content-Range: bytes {$range[0]}-{$range[1]}/".filesize($filename));
    $length=$range[1]-$range[0]+1;
    //put_log("Content-Range: bytes {$range[0]}-{$range[1]}/".filesize($filename));
}
header("Content-Disposition: attachment; filename=\"Ya.exe\"");
if(isset($length)){
    header("HTTP/1.1 206 Partial Content");
    header("Status: 206 Partial Content");
    header("Accept-Ranges: bytes");
    header("Content-Length: ".$length);
    header("Content-Range: bytes {$range[0]}-{$range[1]}/".filesize($filename));
    //put_log("len: $length");
}else {
    header("Accept-Ranges: bytes");
    header("Content-Length: ".filesize($filename));
}
ignore_user_abort(true);
$f=fopen($filename,'rb');
if(isset($range)){
    fseek($f,$range[0]);
}
while (!(connection_aborted() || connection_status() == 1)&&!feof($f)) {
    $cont=fread($f,2048);
    echo $cont;
    flush();
}
fclose($f);
?>


если у кого еще возникнут вопросы по этому поводу обращайтесь по асе(123823)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)