|
|
|
| нужно отдать файл пользователю через скрипт, с возможностью докачки.
копал в нете, сам думал, вот что придумал. как мне казалось поблем быть не должно, однако некоторые телефонные браузеры начинают привиредничать. то вообще не качают, то качают и не сохраняют файл.
посмотрите пожалуйста функцию и если кто-то сможет подсказать где я что не учел, буду очень благодарен =)
<?php
// Содержимое файла, имя файла, аттач (опционально), MIME (опционально)
function getf($f, $name, $attach, $mime)
{
global $_SERVER;
// Длина файла + кодировка
$len = mb_strlen($f,'UTF-8');
$out = $f;
// "От" и "До" по умолчанию
$file_range = array('from' => 0, 'to' => $len);
// Если докачка
if($_SERVER['HTTP_RANGE'])
{
if(preg_match('/bytes=(\d+)-(\d*)/i', $_SERVER['HTTP_RANGE'], $matches))
{
// "От", "До" если "До" нету, "До" равняется размеру файла
$file_range = array('from' => $matches[1], 'to' => ($matches[2] == '') ? $len : $matches[2]);
// Режем переменную в соответствии с данными
if($file_range)
{$out = mb_substr($out, $file_range['from'], $file_range['to']+1, 'UTF-8');}
}
}
// Заголовки...
if($file_range['from'])
{header('HTTP/1.0 206 Partial Content');}
else
{header('HTTP/1.0 200 OK');}
// Ставим MIME в зависимости от расширения
if(!$mime)
{
$info = pathinfo($name);
switch(strtolower($info['extension']))
{
default:
$mime = 'application/octet-stream';
break;
case 'jar':
$mime = 'application/java-archive';
break;
case 'jad':
$mime = 'text/vnd.sun.j2me.app-descriptor';
break;
case 'cab':
$mime = 'application/vnd.ms-cab-compressed';
break;
case 'sis':
$mime = 'application/vnd.symbian.install';
break;
case 'zip':
$mime = 'application/x-zip';
break;
case 'rar':
$mime = 'application/x-rar-compressed';
break;
case '7z':
$mime = 'application/x-7z-compressed';
break;
case 'gz':
case 'tgz':
$mime = 'application/x-gzip';
break;
case 'bz':
case 'bz2':
$mime = 'application/x-bzip';
break;
case 'jpg':
case 'jpe':
case 'jpeg':
$mime = 'image/jpeg';
break;
case 'gif':
$mime = 'image/gif';
break;
case 'png':
$mime = 'image/png';
break;
case 'txt':
$mime = 'text/plain';
break;
case 'mmf':
$mime = 'application/x-smaf';
break;
case 'mid':
$mime = 'audio/mid';
break;
case 'mp3':
$mime = 'audio/mpeg';
break;
case 'amr':
$mime = 'audio/amr';
break;
case 'wav':
$mime = 'audio/x-wav';
break;
case 'mp4':
$mime = 'video/mp4';
break;
case 'wmv':
$mime = 'video/x-ms-wmv';
break;
case '3gp':
$mime = 'video/3gpp';
break;
case 'avi':
$mime = 'video/x-msvideo';
break;
case 'mpg':
case 'mpe':
case 'mpeg':
$mime = 'video/mpeg';
break;
case 'pdf':
$mime = 'application/pdf';
break;
}
}
header('Content-Type: '.$mime);
//header('Last-Modified: '.gmdate('r', time()));
// Кэш
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: cache');
header('Accept-Ranges: bytes');
header('Content-Length: '.mb_strlen($out,'UTF-8'));
// Если докачка
if($_SERVER['HTTP_RANGE'])
{header('Content-Range: bytes '.$file_range['from'].'-'.$file_range['to'].'/'.$len);}
// Хэш
$etag = md5($f);
$etag = substr($etag, 0, 4).'-'.substr($etag, 5, 5).'-'.substr($etag, 10, 8);
header('ETag: "'.$etag.'"');
header('Connection: close');
// Если отдаем как аттач
if($attach)
{header('Content-Disposition: attachment; filename="'.$name.'"');}
print $out;
return;
}
?>
|
ну и работает соответственно примерно так
<?php
$file = file_get_contents('file.zip');
// Файл, имя, аттач, MIME
getf($file,'name.zip',0,0);
?>
|
| |
|
|
|
|
|
|
|
для: Gemorroj
(08.03.2008 в 20:25)
| | Докачка не от скрипта зависит, а от юзер-агента пользователя (браузера) | |
|
|
|
|
|
|
|
для: mihdan
(09.03.2008 в 11:50)
| | и от скрипта тоже. | |
|
|
|
|
|
|
|
для: Gemorroj
(09.03.2008 в 12:24)
| | >и от скрипта тоже.
Просто он должен поддерживать указание позиции, с которой надо продолжить скачку! | |
|
|
|
|
|
|
|
для: ddhvvn
(09.03.2008 в 13:19)
| | ну так а в данном скрипте что не так???
не всегда он почему-то работает. это факт. с оперы 9 и IE 6 проверял - нормально. С нескольких телефонов - не работает. | |
|
|
|
|
|
|
|
для: Gemorroj
(09.03.2008 в 13:24)
| | Вам же сказали - зависит от браузера!!!
Значит в "нескольких телефонах" браузеры не поддерживают докачку! | |
|
|
|
|
|
|
|
для: ddhvvn
(09.03.2008 в 13:47)
| | ну при чем здесь это... посмотрите внимательно на функцию. это учитывается. 206 посылается только если $_SERVER['HTTP_RANGE'] не равно 0 | |
|
|
|
|
|
|
|
для: Gemorroj
(09.03.2008 в 14:44)
| | >... если $_SERVER['HTTP_RANGE'] не равно 0
Я это не вижу!
Вы про
if($_SERVER['HTTP_RANGE'])
|
что ли??? | |
|
|
|
|
|
|
|
для: ddhvvn
(09.03.2008 в 14:45)
| | да, это. не правильно мысля сработала. если начало отрезка ($file_range['from']) равно 0 то отправляется 200. если есть $_SERVER['HTTP_RANGE'] и соответственно $file_range['from'] != 0, то отправляется 206 | |
|
|
|
|
|
|
|
для: Gemorroj
(09.03.2008 в 14:53)
| | http://mobiparade.net/videoobmen/info.php?3gp/5.3gp
вот пример работы данной функции. там еще mod_rewrite, так что я думал даже самые нехорошие браузеры не будут капризничать, ан нет. | |
|
|
|
|
|
|
|
для: Gemorroj
(09.03.2008 в 14:53)
| | Ну а где проверка на ноль то???
Вы проверяете существование переменной, а не равенство нулю!
И опять же: не все браузеры поддерживают докачку! Тем более мобильных телефонов! | |
|
|
|
|
|
|
|
для: ddhvvn
(09.03.2008 в 15:08)
| | >Ну а где проверка на ноль то???
>
>Вы проверяете существование переменной, а не равенство нулю!
При нестрогом сравнении, 0 == false, а значит, выражение
if($_SERVER['HTTP_RANGE'])
|
вернет false, если переменная будет равна нулю. | |
|
|
|
|
|
|
|
для: ddhvvn
(09.03.2008 в 15:08)
| | >Вы проверяете существование переменной, а не равенство нулю!
$var = 0;
// ничего не будет
if($var){
print 'xxx';
}
unset($var);
// ничего не будет
if($var){
print 'xxx';
}
|
т.е. это проверка не только на на существование переменной а еще и на пустое значение (0 в данном случае пустое значение)
>не все браузеры поддерживают докачку
может я что-то не понимаю... но я не вижу в данном случае проблему именно в докачке. если докачка не поддерживается, то соответственно не будет отправляться Content-Range и заголовок будет 200 а не 206
вот какие заголовки получаю если нет $_SERVER['HTTP_RANGE']
HTTP/1.0 200 OK
Date: Sun, 09 Mar 2008 12:10:30 GMT
Server: Apache
Cache-Control: public, must-revalidate, max-age=0
Pragma: cache
Accept-Ranges: bytes
Content-Length: 94161
ETag: "ae1e-b3f42-739daf5a"
Vary: Accept-Encoding
Content-Type: video/3gpp
X-Cache: MISS from turbine2.ht-systems.ru
Connection: close
|
| |
|
|
|