fpassthru()
Функция fpassthru() в PHP читает оставшиеся данные из открытого указателя файла и выводит их в выходной поток.
Что такое функция fpassthru()?
Функция fpassthru() — это встроенная функция PHP, которая читает все оставшиеся данные из открытого указателя файла — начиная с текущей позиции указателя и до конца файла (EOF) — и записывает их напрямую в выходной поток (то, что получает браузер или терминал). Поскольку данные передаются по частям, а не загружаются целиком в строку, функция хорошо подходит для отправки крупных файлов без превышения лимита памяти PHP.
На этой странице рассматриваются синтаксис функции, пошаговый порядок использования, реальный пример загрузки файла, отличия от readfile(), а также важные нюансы.
В случае успеха функция возвращает количество байтов, записанных в вывод, или false при ошибке.
Вот базовый синтаксис функции fpassthru():
Синтаксис fpassthru() в PHP
fpassthru(resource $stream): int|falseГде $stream — это указатель файла, который должен быть корректным и уже открытым (как правило, возвращаемое значение fopen()). После возврата из fpassthru() указатель находится в позиции EOF, а данные уже переданы — прочитать их повторно без перемотки не получится.
Как использовать функцию fpassthru()?
Использование функции fpassthru() довольно простое. Вот шаги, которые нужно выполнить:
- Откройте файл с помощью
fopen()и убедитесь, что указатель файла находится в нужной начальной позиции. - Вызовите
fpassthru()с указателем файла. Функция будет читать до EOF и записывать данные в выходной поток. - Проверьте возвращаемое значение, чтобы убедиться в успешном выполнении, затем закройте файл с помощью
fclose().
Вот пример кода, демонстрирующий использование функции fpassthru():
Как использовать функцию fpassthru()?
<?php
$filename = 'largefile.txt';
$file = fopen($filename, 'r');
if ($file) {
if (fpassthru($file) === false) {
echo "Error reading file!";
}
fclose($file);
} else {
echo "Unable to open file!";
}В этом примере мы открываем файл largefile.txt с помощью функции fopen() в режиме только для чтения. Мы проверяем, успешно ли открылся файл с помощью оператора if, и если да — выводим его содержимое в стандартный выходной поток с помощью fpassthru(). Мы проверяем возвращаемое значение для обработки возможных ошибок чтения, затем закрываем дескриптор с помощью fclose().
Примечание о буферизации вывода: Если буферизация вывода PHP активна (например, через
ob_start()),fpassthru()будет записывать данные непосредственно в текущий буфер вывода, а не отправлять их сразу в браузер.
Чтение с текущей позиции, а не с начала файла
Ключевая особенность заключается в том, что fpassthru() начинает с текущей позиции указателя. Если вы уже прочитали часть файла (например, с помощью fgets() или fread()), будут отправлены только оставшиеся байты. Это позволяет прочитать заголовок самостоятельно и передать остаток потоком:
<?php
$file = fopen('php://temp', 'r+');
fwrite($file, "HEADER\nbody-line-1\nbody-line-2\n");
rewind($file);
// Consume the first line manually.
echo "First line: " . fgets($file);
// Stream everything left after the pointer.
fpassthru($file);
fclose($file);Это выведет:
First line: HEADER
body-line-1
body-line-2Строка HEADER не повторяется, поскольку к моменту запуска fpassthru() указатель уже прошёл её.
Отправка файла как загрузки
Наиболее распространённый случай применения fpassthru() в продакшне — передача файла в браузер в виде загрузки. Задайте нужные заголовки, откройте файл в бинарном режиме ('rb') и позвольте fpassthru() передать байты:
<?php
$path = '/var/www/files/report.pdf';
if (is_readable($path)) {
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="report.pdf"');
header('Content-Length: ' . filesize($path));
$file = fopen($path, 'rb');
fpassthru($file);
fclose($file);
exit;
}
http_response_code(404);
echo 'File not found.';Режим 'rb' важен в Windows, где текстовый режим по умолчанию повредит бинарные данные: изображения, PDF-файлы или архивы. В Linux и macOS флаг b безвреден, поэтому хорошей практикой является всегда включать его для загрузок.
fpassthru() vs. readfile()
Обе функции передают файл в вывод, но работают на разных уровнях:
fpassthru($stream) | readfile($path) | |
|---|---|---|
| Входные данные | Уже открытый указатель файла | Путь к файлу (открывается внутри) |
| Начальная позиция | Текущая позиция указателя | Всегда начало файла |
| Лучше подходит, когда | Нужно прочитать часть файла перед передачей или уже есть открытый дескриптор | Нужно просто вывести весь файл одним вызовом |
Если вам нужно просто вывести весь файл и у вас нет открытого дескриптора, readfile() короче. Используйте fpassthru(), когда уже держите указатель файла или нужно пропустить часть потока.
Заключение
Функция fpassthru() — полезный инструмент в PHP для чтения больших файлов без их загрузки в память. Следуя шагам, описанным в этом руководстве, вы можете легко использовать функцию fpassthru() в своих PHP-проектах для чтения содержимого файлов с текущей позиции указателя и вывода его в стандартный выходной поток.