Перейти к содержимому

Как отдать файл на скачивание php

  • автор:

Отдача файлов на скачивание PHP

В PHP отправка файла в браузер на скачивание осуществляется в 2 этапа:

Отправка заголовков

Первый вариант с явным указанием типа файла mime:

$file = __DIR__ . '/file.avi'; header('Content-Description: File Transfer'); header('Content-Type: video/x-msvideo'); header('Content-Disposition: attachment; filename=' . basename($file)); header('Content-Transfer-Encoding: binary'); header('Content-Length: ' . filesize($file));

Второй, application/octet-stream – «двоичный файл без указания формата».

$file = __DIR__ . '/file.avi'; header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); header('Content-Transfer-Encoding: binary'); header('Content-Length: ' . filesize($file));

Заголовок с размером файла – header(‘Content-Length: ‘ . filesize($file)); можно не указывать.

Чтение и вывод файла

Перед отправкой файла нужно убедится что буферизация вывода отключена с помощью ob_get_level() или сбросить и отключить ее функцией ob_end_clean() .

Непосредственно чтение и вывод файла можно сделать следующими функциями:

readfile
readfile($file); exit();

Как отдать файл на скачивание но при этом подменить имя скачиваемого файла?

Если на такую ссылку кликнуть то файл 556544.doc скачаеться как 10 тестовый файл.doc все супер, как это повторить на JQuery или на php? UPD Сейчас на php сделал так.

if(isset($_GET["file"])) < $fileid = $_GET["file"]; $sql_downloadfile = "SELECT * FROM `files` WHERE `id`=".$fileid; $result_downloadfile = mysqli_query($db,$sql_downloadfile) or die("Ошибка: " . mysqli_error($db)); if(mysqli_num_rows($result_downloadfile) >0) < $file = mysqli_fetch_array($result_downloadfile); $filelink = "http://mysite.ru/panel/files/".$file["localfile_title"]; // заставляем браузер показать окно сохранения файла header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($filelink)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); // читаем файл и отправляем его пользователю readfile($filelink); >else < echo 'ФАЙЛ НЕ НАЙДЕН!'; >>

Как изменить имя для качаемого файла? Вопрос рише

header('Content-Disposition: attachment; header('Content-Disposition: attachment; filename="'.$new_file_name.'"'); 

Отдаем файлы эффективно с помощью PHP

Метод хорош тем, что работает с коробки. Надо только написать свою функцию отправки файла (немного измененный пример из официальной документации):

function file_force_download($file) < if (file_exists($file)) < // сбрасываем буфер вывода PHP, чтобы избежать переполнения памяти выделенной под скрипт // если этого не сделать файл будет читаться в память полностью! if (ob_get_level()) < ob_end_clean(); >// заставляем браузер показать окно сохранения файла header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); // читаем файл и отправляем его пользователю readfile($file); exit; > > 

Таким способом можно отправлять даже большие файлы, так как PHP будет читать файл и сразу отдавать его пользователю по частям. В документации четко сказано, что readfile() не должен создавать проблемы с памятью.

  • Скрипт ждет пока весь файл будет прочитан и отдан пользователю.
  • Файл читается в внутренний буфер функции readfile(), размер которого составляет 8кБ (спасибо 2fast4rabbit)
2. Читаем и отправляем файл вручную

Метод использует тот же Drupal при отправке файлов из приватной файловой системы (файлы недоступны напрямую по ссылкам):

function file_force_download($file) < if (file_exists($file)) < // сбрасываем буфер вывода PHP, чтобы избежать переполнения памяти выделенной под скрипт // если этого не сделать файл будет читаться в память полностью! if (ob_get_level()) < ob_end_clean(); >// заставляем браузер показать окно сохранения файла header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); // читаем файл и отправляем его пользователю if ($fd = fopen($file, 'rb')) < while (!feof($fd)) < print fread($fd, 1024); >fclose($fd); > exit; > > 
  • Скрипт ждет пока весь файл будет прочитан и отдан пользователю.
  • Позволяет сэкономить память сервера
3. Используем модуль веб сервера
3a. Apache

Модуль XSendFile позволяет с помощью специального заголовка передать отправку файла самому Apache. Существуют версии по Unix и Windows, под версии 2.0.*, 2.2.* и 2.4.*

В настройках хоста нужно включить перехват заголовка с помощью директивы:

XSendFile On 

Также можно указать белый список директорий, файлы в которых могут быть обработаны. Важно: если у Вас сервер на базе Windows путь должен включать букву диска в верхнем регистре.

Описание возможных опций на сайте разработчика: https://tn123.org/mod_xsendfile/

Пример отправки файла:

function file_force_download($file) < if (file_exists($file)) < header('X-SendFile: ' . realpath($file)); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); exit; >> 
3b. Nginx

Nginx умеет отправлять файлы из коробки через специальный заголовок.

Для корректной работы нужно запретить доступ к папку напрямую через конфигурационный файл:

location /protected/ < internal; root /some/path; >

Пример отправки файла (файл должен находиться в директории /some/path/protected):

function file_force_download($file) < if (file_exists($file)) < header('X-Accel-Redirect: ' . $file); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); exit; >> 

Больше информации на странице официальной документации

  • Скрипт завершается сразу после выполнения всех инструкций
  • Физически файл отправляется модулем самого веб сервера, а не PHP
  • Минимальное потребление памяти и ресурсов сервера
  • Максимальное быстродействие

Update: Хабраюзер ilyaplot дает дельный совет, что лучше слать не application/octet-stream , а реальный mime type файла. Например, это позволит браузеру подставить нужные программы в диалог сохранение файла.

Как на PHP скачать файл

Для того, чтобы отдать файл на скачивание, при помощи скрипта PHP, нужно всего-лишь прописать несколько заголовков, при помощи функции void header ( string string [, bool replace [, int http_response_code]] ) и прочитать файл при помощи функции int readfile ( string filename [, bool use_include_path [, resource context]] ) .

Пример

Например файл у нас хранится в папке files/public/download.rar , нам нужно, чтобы файл download.php начинал скачивание нужного нам файла.

Создаем файл download.php и прописываем следующий код.

Заключение

Скачивать файлы средствами PHP очень просто, код этот можно вынести в отдельную функцию, и передавать в качестве параметра имя файла.

✖ ❤ Мне помогла статья 3 оценки
11486 просмотров нет комментариев Артём Фёдоров 21 марта 2011

Категории

Читайте также

  • Скачать файл с сервера (PHP)
  • Как записать массив в файл (PHP)
  • Как скопировать файл (PHP)
  • Как создать файл (PHP)
  • Как очистить файл не удаляя его (PHP)
  • Как очистить папку (PHP)
  • Как проверить права доступа (PHP)
  • Дата изменения файла (PHP)
  • Singleton Trait (PHP)
  • Редирект (PHP)
  • Склонение числительных на PHP
  • Транслит (PHP)

Комментарии

Написать комментарий
© Экспэнч 2010-2024
При полном или частичном копировании статей сайта указывайте пожалуйста ссылку на источник
Хотите узнать больше информации, пишите на: artem@expange.ru

Вход на сайт

Введите данные указанные при регистрации:

Социальные сети

Вы можете быстро войти через социальные сети:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *