|
|
|
| Давно возник вопрос, как представить пользователю файл для скачивания, и не выдать прямую ссылку.
Допустим файл file.mkv 9.5 GB
php4 - 4000 Mb max php5 - 700 mb. функция copy();
и то это я на сервере вытворяю такое, а на хостинге понятно никто таких ресурсов не даст.
как рационально используя ресурсы предоставить пользователю файл для скачивания?
не хочу чтоб пользователи видели адрес к оригиналу файла. хочу дать другую ссылку для скачивания.
или можна скопировать файл по частям ?
подскажите как это делают... | |
|
|
|
|
|
|
|
для: toproot
(07.09.2010 в 23:58)
| | что это ?
php4 - 4000 Mb max php5 - 700 mb. функция copy();
файл пользователю предоставляется путем реализации алгоритма частичной докачки. (PARTIAL CONTENT)
Потому что даже на меньших на три порядка ( в тысячу раз) файлах, отдавать файл одним куском - форменное издевательство.
Для реализации понадобятся fopen, fseek, fpassthru ... и пожалуй всё.
Затрат по памяти у этих функций нет никаких. Во всяком случае - пропорциональных размерам файла.
Если Вы ведете речь о том, что адресные пространства fseek ftell в 32битных имплементациях php ограничены четырьмя, а то и двумя гигами... Ну что тут можно сказать... Очевидно, там, где у Вас появятся файлы бОльшего размера, php будет уже 64-битный. Со всеми вытекающими. | |
|
|
|
|
|
|
|
для: Trianon
(08.09.2010 в 00:29)
| | Да Огромное спасибо.
вот решил проблему:
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));
if ($range) {
header("Content-Range: bytes $range-".($fsize - 1).'/'.$fsize);
}
header('Content-Type: '.$mimetype);
fpassthru($fd); // отдаем часть файла в браузер (программу докачки)
fclose($fd);
exit;
}
|
| |
|
|
|
|
|
|
|
для: toproot
(09.09.2010 в 15:57)
| | if (!empty($range)) {
fseek($fd, $range);
}
вот тут надо учесть, что если $range == '' в то время как $end != '', то fseek($fd, -$end, SEEK_END);
случай редкий, но в RFC он всё же есть.
А если заданы и левый и правый параметр (при чем последний недотягивает до фактического конца файла, то корректнее отдавать контент порционно. | |
|
|
|