W3docs

fpassthru()

Функция fpassthru() в PHP читает оставшиеся данные из открытого указателя файла и выводит их в выходной поток.

Что такое функция fpassthru()?

Функция fpassthru() — это встроенная функция PHP, которая читает все оставшиеся данные из открытого указателя файла — начиная с текущей позиции указателя и до конца файла (EOF) — и записывает их напрямую в выходной поток (то, что получает браузер или терминал). Поскольку данные передаются по частям, а не загружаются целиком в строку, функция хорошо подходит для отправки крупных файлов без превышения лимита памяти PHP.

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

В случае успеха функция возвращает количество байтов, записанных в вывод, или false при ошибке.

Вот базовый синтаксис функции fpassthru():

Синтаксис fpassthru() в PHP

fpassthru(resource $stream): int|false

Где $stream — это указатель файла, который должен быть корректным и уже открытым (как правило, возвращаемое значение fopen()). После возврата из fpassthru() указатель находится в позиции EOF, а данные уже переданы — прочитать их повторно без перемотки не получится.

Как использовать функцию fpassthru()?

Использование функции fpassthru() довольно простое. Вот шаги, которые нужно выполнить:

  1. Откройте файл с помощью fopen() и убедитесь, что указатель файла находится в нужной начальной позиции.
  2. Вызовите fpassthru() с указателем файла. Функция будет читать до EOF и записывать данные в выходной поток.
  3. Проверьте возвращаемое значение, чтобы убедиться в успешном выполнении, затем закройте файл с помощью 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-проектах для чтения содержимого файлов с текущей позиции указателя и вывода его в стандартный выходной поток.

Практика

Практика
В чём назначение функции fpassthru() в PHP?
В чём назначение функции fpassthru() в PHP?
Was this page helpful?