Чанкинг файлов - это самый быстрый / простой метод в PHP, если вы не можете или не хотите использовать что-то более профессиональное, например, cURL , mod-xsendfile
on Apache или какой-то выделенный скрипт .
$filename = $filePath.$filename;
$chunksize = 5 * (1024 * 1024); //5 MB (= 5 242 880 bytes) per one chunk of file.
if(file_exists($filename))
{
set_time_limit(300);
$size = intval(sprintf("%u", filesize($filename)));
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$size);
header('Content-Disposition: attachment;filename="'.basename($filename).'"');
if($size > $chunksize)
{
$handle = fopen($filename, 'rb');
while (!feof($handle))
{
print(@fread($handle, $chunksize));
ob_flush();
flush();
}
fclose($handle);
}
else readfile($path);
exit;
}
else echo 'File "'.$filename.'" does not exist!';
Портировано с richnetapps.com / NeedBee . Протестировано на 200 МБ файлах, на которых умерла readfile()
, даже с максимально допустимым пределом памяти, установленным на 1G
, что в пять раз больше размера загружаемого файла.
Кстати: я проверял это также на файлах >2GB
, но PHP удалось записать только сначала 2GB
файла, а затем разорвал соединение. Связанные с файлами функции (fopen, fread, fseek) используют INT, поэтому вы в конечном итоге достигнете предела 2GB
. Вышеупомянутые решения (т.е. mod-xsendfile
), по-видимому, являются единственным вариантом в этом случае.
РЕДАКТИРОВАТЬ : Убедитесь, 100% , что ваш файл сохранен в utf-8
. Если вы пропустите это, загруженные файлы будут повреждены. Это потому, что в этом решении используется print
для передачи фрагмента файла в браузер.