Автор: AcTEpi_X 23.9.2008, 16:45
Сейчас всё более популярными становятся сервисы, предоставляющие файлы на скачивание. Разумеется, при этом возникают вопросы: как устроен сервис, как делают временные ссылки, как получается что адрес файла в виде кракозябр, а скачивается с нормальным именем, как делают названия файлов в транслитерации и т.д. Все эти вопросы являются актуальными, поскольку первые критичны в плане безопасности, вторые являются чисто экономическими и направлены на ограничения скачивания,
третьи связаны с необходимостью обеспечения совместимости между разными
операционными системами.
В этой статье я затрону лишь ядро сервиса - загрузку файлов с сервера на локальный компьютер.
Приведёная функция позволяет читать файлы с сервера и отдавать клиенту для сохранения на компьютер.
Код
<?php
define(’FTP_ROOT_DIRECTORY’,'/var/www/ftp’);
$file[’link ’] = “/soft/scorpion/myPhpscripts.zip”;
$file[’name’] = ”Сборник_php_скриптов_Скорпиона.zip”;
$filename = FTP_ROOT_DIRECTORY.$file[’link’];
if(!file_exists($filename)){
header($_SERVER[”SERVER_PROTOCOL”].” 404 Not Found”);
exit;
}
$fsize = filesize($filename);
$ftime = date(”D, d M Y H:i:s T”, filemtime($filename));
$fd = fopen($filename, “rb”);
if(!$fd){
header($_SERVER[”SERVER_PROTOCOL”].” 403 Forbidden”);
exit;
}
if($_SERVER[”HTTP_RANGE”]){
$range = $_SERVER[”HTTP_RANGE”];
$range = str_replace(”bytes=”, “”, $range);
$range = str_replace(”-”, “”, $range);
if($range) fseek($fd, $range);
}
if($range) header($_SERVER[”SERVER_PROTOCOL”].” 206 Partial Content”);
else header($_SERVER[”SERVER_PROTOCOL”].” 200 OK”);
header(”Content-Disposition: attachment; filename=”.$file[’name’]);
header(”Last-Modified: “.$ftime);
header(”Accept-Ranges: bytes”);
header(”Content-Length: ” .($fsize-$range));
header(”Content-Range: bytes “.$range-($fsize -1)/$fsize);
header(”Content-Type: application/octet-stream”);
while (!feof($fd)){
echo fread($fd,(1024*10));
}
fclose($fd);
?>
В результате выполнения скрипта скачается файл с именем указаным в $file[’name’].
Некоторые моменты я позаимствовал из других подобных функций, размешёных в интернет. Вы, наверное это заметили, если искали подобный скрипт на просторах сети. Ключевое отличие заключается в способе чтения. Как правило, подобные функции читают сразу весь файл в переменную. На мой взгляд это неправильно. Более того, моё мнение сформировалось при тестировании опытным путём. Дело в том, что если читать в переменную весь файл сразу и при этом объём файла достаточно большой, вместо загрузки файла открывается страница: файл не найден. Поэтому, рекомендую читать файл по частям, вот так:
Код
while (!feof($fd)){
echo fread($fd,(1024*10));
}
Обратите внимание: данный скрипт поддерживает докачку. Следовательно, если у ваших клиентов прервалась связь, ничего страшного: в следующий сеанс связи файл можно докачать.
http://scorpion.amateria.ru/2007/10/02/zagruzka-fajla-po-http.html