Как передать файл пользователю в браузере на php?
Ответ
Пример с официальной документации, который многократно был проверен:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function send_file($filename) { if (file_exists($filename)) { // чтобы избежать переполнение буфера if (ob_get_level()) { ob_end_clean(); } header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($filename)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($filename)); readfile($filename); exit; } } |
Большие файлы PHP будет передавать частями, поэтому проблем с памятью возникать не должно.
Применить данную фунцию можно так:
Файл file.php
1 |
send_file('test.txt'); |
Файл index.php
1 |
<a href="file.php">Скачать файл</a> |
Еще одно замечание: если нет уверенности, что название файла не будет содержать пробелы, то стоит строку
1 |
header('Content-Disposition: attachment; filename=' . basename($filename)); |
заменить на
1 |
header('Content-Disposition: attachment; filename="'.basename($file).'"' ); |
И еще один фрагмент кода, который может пригодиться, если вы хотите ограничить скорость передачи файла:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
$local_file = 'file.zip'; $download_file = 'name.zip'; // устанавливаем скорость (например, 20,5 kb/s) $download_rate = 20.5; if(file_exists($local_file) && is_file($local_file)) { header('Cache-control: private'); header('Content-Type: application/octet-stream'); header('Content-Length: '.filesize($local_file)); header('Content-Disposition: filename='.$download_file); flush(); $file = fopen($local_file, "r"); while(!feof($file)) { // отправляем очередную часть файла в браузер print fread($file, round($download_rate * 1024)); flush(); // пауза 1 секунда sleep(1); } fclose($file); } else { die('Ошибка. Файл '.$local_file.' не существует'); } |