|
|
|
| Здравствуйте:)
Написал файлообменник. Но так как загрузка файла из него можно сказать нехалявная (за поинты определенные), то загрузку осуществляю через php-файл. Но при таком скачивании постоянно выдается ошибка и загрузку приходится возобновлять.
На данный момент использую для вывода файла через скрипт следующую функцию, которую нашёл в интернете:
function downloadFile($filename, $mimetype='application/octet-stream') {
if (!file_exists($filename)) die('Файл не найден');
$from=$to=0; $cr=NULL;
if (isset($_SERVER['HTTP_RANGE'])) {
$range=substr($_SERVER['HTTP_RANGE'], strpos($_SERVER['HTTP_RANGE'], '=')+1);
$from=strtok($range, '-');
$to=strtok('/'); if ($to>0) $to++;
if ($to) $to-=$from;
header('HTTP/1.1 206 Partial Content');
$cr='Content-Range: bytes ' . $from . '-' . (($to)?($to . '/' . $to+1):filesize($filename));
} else header('HTTP/1.1 200 Ok');
$etag=md5($filename);
$etag=substr($etag, 0, 8) . '-' . substr($etag, 8, 7) . '-' . substr($etag, 15, 8);
header('ETag: "' . $etag . '"');
header('Accept-Ranges: bytes');
header('Content-Length: ' . (filesize($filename)-$to+$from));
if ($cr) header($cr);
header('Connection: close');
header('Content-Type: ' . $mimetype);
header('Last-Modified: ' . gmdate('r', filemtime($filename)));
$f=fopen($filename, 'r');
header('Content-Disposition: attachment; filename="' . basename($filename) . '";');
if ($from) fseek($f, $from, SEEK_SET);
if (!isset($to) or empty($to)) {
$size=filesize($filename)-$from;
} else {
$size=$to;
}
$downloaded=0;
while(!feof($f) and !connection_status() and ($downloaded<$size)) {
echo fread($f, 512000);
$downloaded+=512000;
flush();
}
fclose($f);
}
|
Плюс этой функции в том, что хоть докачку файла поддерживает, а то без докачки вообще скачать невозможно, т.к. за время скачивания ошибок 5 возникнет. Но не у всех браузеров есть докачка и возобновление загрузки после ошибки!
Как быть? В чем проблема? Проблема в php-скрипте или же это уже прихоти сервера?
Как например другие коммерческие файлообменники дают скачивать файлы через скрипт без всяких сбоев? | |
|
|
|
|
|
|
|
для: Xzed
(21.07.2009 в 21:45)
| | А если скачивать теже файлы без скрипта а напрямую по ссылке? Тоже обрывы происходят?
поиграй с размером буфера, попробуй уменьшить его fread($f, 512000); | |
|
|
|
|
|
|
|
для: Петр
(22.07.2009 в 09:41)
| | Напрямую (не через скрипт) качает отлично.
Спасибо за совет насчёт буфера.
Кстати, а может есть какие либо другие алгоритмы или решения для отдачи файла юзеру за поинты?
Вот также нашел альтернативную функцию:
// $filepath – путь к файлу, который мы хотим отдать
// $mimetype – тип отдаваемых данных (можно не менять)
function func_download_file($filepath, $mimetype = 'application/octet-stream') {
$fsize = filesize($filepath); // берем размер файла
$ftime = date('D, d M Y H:i:s T', filemtime($filepath)); // определяем дату его модификации
$fd = @fopen($filepath, 'rb'); // открываем файл на чтение в бинарном режиме
if (isset($_SERVER['HTTP_RANGE'])) { // поддерживается ли докачка?
$range = $_SERVER['HTTP_RANGE']; // определяем, с какого байта скачивать файл
$range = str_replace('bytes=', '', $range);
list($range, $end) = explode('-', $range);
if (!empty($range)) {
fseek($fd, $range);
}
} else { // докачка не поддерживается
$range = 0;
}
if ($range) {
header($_SERVER['SERVER_PROTOCOL'].' 206 Partial Content'); // говорим браузеру, что это часть какого-то контента
} else {
header($_SERVER['SERVER_PROTOCOL'].' 200 OK'); // стандартный ответ браузеру
}
// прочие заголовки, необходимые для правильной работы
header('Content-Disposition: attachment; filename='.basename($filepath));
header('Last-Modified: '.$ftime);
header('Accept-Ranges: bytes');
header('Content-Length: '.($fsize - $range));
header("Content-Range: bytes $range-".($fsize - 1).'/'.$fsize);
header('Content-Type: '.$mimetype);
header('Content-transfer-encoding: binary');
fpassthru($fd); // отдаем часть файла в браузер (программу докачки)
fclose($fd);
exit;
}
|
Результат тоже не особо радует. Также обрывает.
Кто использует такие же функции в своих скриптах? Поделитесь опытом, расскажите как у Вас скачивает файлы через эту функцию и какой у Вас интернет?
Если проблему не решим, то хотя бы диагностику проведем, а дальше думать будем... | |
|
|
|
|
|
|
|
для: Xzed
(22.07.2009 в 21:30)
| | Ничего не помогает. У тех кто сидит с GPRS-интернетом (а у меня как раз WAP-сайт) или модемом никогда ничего таким образом не скачает.
Да и такой скрипт нагрузку на сервер будет немалую создавать при приличной посещаемости.
Вывод таков: надо искать другие пути решения отдачи файлов юзерам ненапрямую. Или...
Помимо того, что скрипт считает количество скачиваний и отнимает у юзеров поинты, он ещё и выполняет защитную функцию.
Права на папки в файлообменнике как правилo 777. То есть злоумышленник, найдя способ залить шел, наверняка воспользуется данными папками. Но у меня доступ к файлам в этих папка закрыт .htaccessом (строчкой Deny from all), поэтому скачать (запустить) файл можно только через скрипт, а скачать через скрипт можно только промодерированные файлы. Поэтому я бы и мог сделать юзерам скачивание файлов без всяких поинтов, а счётчик сделал бы типа
<?
счётчик=счётчик+1
header("Location: прямая ссылка на файл");
?>
|
Но если я открою публичный доступ к папкам файлообменника, чтобы качать файлы напрямую, то появится потенциальная угроза.
Вопрос в следующем: можно ли каким-либо образом разрешить серверу хранить в папках файлы только определенного формата и mime-типа?
Например в папке music, чтобы были только *.mp3, а если будет какой-либо *.php, то сервер просто выдаст типа "Forbidden" или "Not found"? | |
|
|
|