Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: отдать файл с возможностью докачки
 
 автор: Gemorroj   (08.03.2008 в 20:25)   письмо автору
 
 

нужно отдать файл пользователю через скрипт, с возможностью докачки.
копал в нете, сам думал, вот что придумал. как мне казалось поблем быть не должно, однако некоторые телефонные браузеры начинают привиредничать. то вообще не качают, то качают и не сохраняют файл.
посмотрите пожалуйста функцию и если кто-то сможет подсказать где я что не учел, буду очень благодарен =)
<?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($etag04).'-'.substr($etag55).'-'.substr($etag108);
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);
?>

   
 
 автор: mihdan   (09.03.2008 в 11:50)   письмо автору
 
   для: Gemorroj   (08.03.2008 в 20:25)
 

Докачка не от скрипта зависит, а от юзер-агента пользователя (браузера)

   
 
 автор: Gemorroj   (09.03.2008 в 12:24)   письмо автору
 
   для: mihdan   (09.03.2008 в 11:50)
 

и от скрипта тоже.

   
 
 автор: ddhvvn   (09.03.2008 в 13:19)   письмо автору
 
   для: Gemorroj   (09.03.2008 в 12:24)
 

>и от скрипта тоже.

Просто он должен поддерживать указание позиции, с которой надо продолжить скачку!

   
 
 автор: Gemorroj   (09.03.2008 в 13:24)   письмо автору
 
   для: ddhvvn   (09.03.2008 в 13:19)
 

ну так а в данном скрипте что не так???
не всегда он почему-то работает. это факт. с оперы 9 и IE 6 проверял - нормально. С нескольких телефонов - не работает.

   
 
 автор: ddhvvn   (09.03.2008 в 13:47)   письмо автору
 
   для: Gemorroj   (09.03.2008 в 13:24)
 

Вам же сказали - зависит от браузера!!!
Значит в "нескольких телефонах" браузеры не поддерживают докачку!

   
 
 автор: Gemorroj   (09.03.2008 в 14:44)   письмо автору
 
   для: ddhvvn   (09.03.2008 в 13:47)
 

ну при чем здесь это... посмотрите внимательно на функцию. это учитывается. 206 посылается только если $_SERVER['HTTP_RANGE'] не равно 0

   
 
 автор: ddhvvn   (09.03.2008 в 14:45)   письмо автору
 
   для: Gemorroj   (09.03.2008 в 14:44)
 

>... если $_SERVER['HTTP_RANGE'] не равно 0

Я это не вижу!
Вы про
if($_SERVER['HTTP_RANGE'])

что ли???

   
 
 автор: Gemorroj   (09.03.2008 в 14:53)   письмо автору
 
   для: ddhvvn   (09.03.2008 в 14:45)
 

да, это. не правильно мысля сработала. если начало отрезка ($file_range['from']) равно 0 то отправляется 200. если есть $_SERVER['HTTP_RANGE'] и соответственно $file_range['from'] != 0, то отправляется 206

   
 
 автор: Gemorroj   (09.03.2008 в 15:05)   письмо автору
 
   для: Gemorroj   (09.03.2008 в 14:53)
 

http://mobiparade.net/videoobmen/info.php?3gp/5.3gp
вот пример работы данной функции. там еще mod_rewrite, так что я думал даже самые нехорошие браузеры не будут капризничать, ан нет.

   
 
 автор: ddhvvn   (09.03.2008 в 15:08)   письмо автору
 
   для: Gemorroj   (09.03.2008 в 14:53)
 

Ну а где проверка на ноль то???

Вы проверяете существование переменной, а не равенство нулю!

И опять же: не все браузеры поддерживают докачку! Тем более мобильных телефонов!

   
 
 автор: Drago   (09.03.2008 в 15:15)   письмо автору
 
   для: ddhvvn   (09.03.2008 в 15:08)
 

>Ну а где проверка на ноль то???
>
>Вы проверяете существование переменной, а не равенство нулю!

При нестрогом сравнении, 0 == false, а значит, выражение
if($_SERVER['HTTP_RANGE'])

вернет false, если переменная будет равна нулю.

   
 
 автор: Gemorroj   (09.03.2008 в 15:21)   письмо автору
 
   для: 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

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования