Скачивание файлов в PHP: от простого к сложному

Раздел: PHP веб-разработка -> работа с файлами

Скачать страницу PHP: варианты принудительной выдачи файла

Как сделать, чтобы PHP отдавал результат скрипта как файл для скачивания?

Основной способ: отправка заголовков и чтение файла

Наиболее эффективное решение использует функцию header() для установки MIME-типа и Content-Disposition, а затем readfile() для вывода содержимого. Этот подход работает с любыми файлами, хранящимися на сервере.


// Файл download.php
$file = 'path/to/document.pdf';
$filename = basename($file);

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
} else {
    echo 'Файл не найден.';
}

Include system php (включение системного файла)

Пояснение: Content-Disposition: attachment заставляет браузер открыть диалог сохранения. filesize() добавляет правильную длину контента. readfile() выводит содержимое порциями, экономя память.

Типичная ошибка:

Вывод пробелов или предупреждений до вызова header() приводит к ошибке headers already sent. Решение: убедиться, что перед header() нет вывода (echo, HTML, пробелы до <?php). Использовать ob_start() для буферизации вывода.

Как сохранить результат выполнения PHP-скрипта в файл на сервере?

Используется комбинация ob_start() и file_put_contents() для захвата всего вывода скрипта.


ob_start(); // начало буферизации вывода

echo '<html><body>...</body></html>';

$content = ob_get_clean(); // получение и очистка буфера
file_put_contents('cached_page.html', $content);

Ru reading php line (чтение строки из файла php)

Такой вариант полезен для кэширования динамических страниц или генерации статических HTML-копий.

Ошибка: если вызывать ob_get_clean() до закрытия буфера, результат может быть пустым. Проверить вложенность буферов.

Как скачать удалённую страницу через PHP?

Для получения содержимого внешнего URL применяется file_get_contents() или cURL. Затем результат можно отдать пользователю.


$url = 'https://example.com/page.php';
$content = file_get_contents($url);

header('Content-Type: text/html');
header('Content-Disposition: attachment; filename="page.html"');
echo $content;

Php file get html (получение html файла через php)

При больших объёмах данных лучше использовать cURL с потоковой записью, чтобы не перегружать память.

Проблема: file_get_contents() может быть заблокирован на сервере (allow_url_fopen = Off). В таком случае применяется cURL.

Как обеспечить скачивание файла через прямую ссылку с атрибутом download?

В HTML5 можно просто добавить атрибут download к ссылке, указывающей на PHP-скрипт, который выводит файл. Это не требует отдельного PHP-обработчика.


<a href="download.php" download>Скачать файл</a>

Скрипт download.php должен выводить нужные заголовки.

- Edit home php (редактирование файла home.php)
- Php количество файлов (подсчет количества файлов в папке в php)
- Archive php file (php: работа с архивными файлами (zip, tar))

Расширенные примеры скачивания файлов через PHP

Пример 1. Скачивание динамически созданного CSV-файла

Пример

// generate_csv.php
$data = [
    ['Имя', 'Email', 'Дата'],
    ['Иван', 'ivan@example.com', '2024-01-15'],
    ['Мария', 'maria@example.com', '2024-02-20']
];

header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="contacts.csv"');

$output = fopen('php://output', 'w');
fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF)); // BOM для Excel
foreach ($data as $row) {
    fputcsv($output, $row);
}
fclose($output);
Результат: браузер скачивает файл contacts.csv с корректной кодировкой UTF-8.

Пример 2. Скачивание файла с проверкой прав доступа

Пример

// secure_download.php
session_start();
if (!isset($_SESSION['user'])) {
    header('HTTP/1.0 403 Forbidden');
    echo 'Доступ запрещён';
    exit;
}

$file = '/var/www/private/data.txt';
if (!file_exists($file) || !is_readable($file)) {
    header('HTTP/1.0 404 Not Found');
    exit;
}

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="data.txt"');
header('Content-Length: ' . filesize($file));
readfile($file);
Результат: файл скачивается только для авторизованных пользователей.

Пример 3. Скачивание большого файла с прогрессом через X-Sendfile (Apache/Nginx)

Пример

// xsendfile.php
$file = '/var/www/large_video.mp4';
header('X-Sendfile: ' . $file);
header('Content-Type: video/mp4');
header('Content-Disposition: attachment; filename="video.mp4"');
exit;
Результат: веб-сервер отдаёт файл напрямую, не нагружая PHP. Требуется модуль mod_xsendfile.

Пример 4. Скачивание архива из нескольких файлов на лету

Пример

// zip_download.php
$zip = new ZipArchive();
$tmp = tempnam(sys_get_temp_dir(), 'zip');
if ($zip->open($tmp, ZipArchive::CREATE) !== TRUE) {
    exit('Ошибка создания архива');
}

$zip->addFile('doc1.pdf', 'doc1.pdf');
$zip->addFile('doc2.pdf', 'doc2.pdf');
$zip->close();

header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="documents.zip"');
header('Content-Length: ' . filesize($tmp));
readfile($tmp);
unlink($tmp); // удаляем временный файл
Результат: скачивается ZIP-архив, созданный динамически.

Пример 5. Скачивание с возобновлением (Range запросы)

Пример

// resume_download.php
$file = 'largefile.iso';
$fp = fopen($file, 'rb');
$size = filesize($file);
$start = 0;
$end = $size - 1;

if (isset($_SERVER['HTTP_RANGE'])) {
    preg_match('/bytes=(\d+)-(\d*)/', $_SERVER['HTTP_RANGE'], $matches);
    $start = intval($matches[1]);
    $end = ($matches[2] === '') ? $size - 1 : intval($matches[2]);
    header('HTTP/1.1 206 Partial Content');
    header('Content-Range: bytes ' . $start . '-' . $end . '/' . $size);
} else {
    header('HTTP/1.1 200 OK');
}

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="largefile.iso"');
header('Content-Length: ' . ($end - $start + 1));
fseek($fp, $start);
$chunkSize = 1024 * 1024; // 1 MB
while (!feof($fp) && ftell($fp) <= $end) {
    $remaining = $end - ftell($fp) + 1;
    if ($remaining < $chunkSize) $chunkSize = $remaining;
    echo fread($fp, $chunkSize);
    flush();
}
fclose($fp);
Результат: поддерживается докачка больших файлов.

скачать страницу PHP (файл) - comments

En
скачать страницу php (php)