Fpassthru: примеры (PHP)

Функция fpassthru: передача данных из файлового указателя
Раздел: Работа с файлами
fpassthru(resource $stream): int
Описание функции fpassthru

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

Аргументы функции

Функция принимает один обязательный параметр:

  • $stream (resource) — файловый указатель, полученный с помощью функций типа fopen(). Указатель должен быть открыт для чтения.
Возвращаемое значение

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

Когда используется

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

Базовые примеры использования
Пример 1: Вывод текстового файла

Код:

<?
$handle = fopen('example.txt', 'r');
if ($handle) {
    $bytes = fpassthru($handle);
    fclose($handle);
    echo "\nПередано байт: $bytes";
}
?>

Предполагая, что example.txt содержит текст 'Привет, мир!', результат:

Привет, мир!
Передано байт: 13
Пример 2: Передача изображения с заголовками

Код:

<?
$filePath = 'image.jpg';
$handle = fopen($filePath, 'rb');
if ($handle) {
    header('Content-Type: image/jpeg');
    header('Content-Length: ' . filesize($filePath));
    fpassthru($handle);
    fclose($handle);
    exit;
}
?>

Результат: браузер отобразит изображение JPEG.

Похожие функции в PHP

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

stream_copy_to_stream()

Копирует данные из одного потока в другой. Позволяет передавать данные между любыми потоками (например, из файла в сокет) с указанием длины копируемых данных.

fread() + echo

Чтение файла блоками и вывод через echo. Требует больше кода, но даёт полный контроль над процессом чтения и буферизацией.

Выбор функции

fpassthru предпочтительнее, когда файл уже открыт и нужно вывести остаток данных. readfile проще для вывода целого файла. stream_copy_to_stream гибче для работы с разными потоками.

Аналоги в других языках

Fpassthru в Python

Используется метод shutil.copyfileobj() или прямое чтение и запись.

with open('file.txt', 'rb') as f:
    for chunk in iter(lambda: f.read(4096), b''):
        sys.stdout.buffer.write(chunk)
JavaScript (Node.js)

Создание читаемого потока и передача в ответ.

const fs = require('fs');
const readStream = fs.createReadStream('file.txt');
readStream.pipe(res); // res - объект ответа HTTP

Fpassthru в MySQL

Прямого аналога нет, но для вывода содержимого файла в виде строки можно использовать LOAD_FILE().

SELECT LOAD_FILE('/path/to/file.txt') AS file_content;
Отличия от PHP

В PHP fpassthru работает с уже открытым ресурсом потока, в то время как аналоги в других языках часто объединяют открытие и передачу или используют потоковые API.

Типичные ошибки
1. Попытка использовать закрытый или невалидный указатель
<?
$handle = fopen('file.txt', 'r');
fclose($handle);
$result = fpassthru($handle); // Warning: ...
?>
Warning: fpassthru(): supplied resource is not a valid stream resource
2. Отправка заголовков после вывода данных
<?
$handle = fopen('image.jpg', 'rb');
fpassthru($handle);
header('Content-Type: image/jpeg'); // Ошибка: заголовки уже отправлены
?>
3. Файл открыт не для чтения
<?
$handle = fopen('file.txt', 'w'); // Открыт для записи
fpassthru($handle); // Не сработает
?>
Изменения в PHP 8

В PHP 8 не было внесено значительных изменений в поведение функции fpassthru. Важным общим изменением в PHP 8 является более строгая типизация — передача неправильного типа аргумента теперь вызовет TypeError вместо предупреждения.

<?
fpassthru('not_a_resource');
?>
TypeError: fpassthru(): Argument #1 ($stream) must be of type resource, string given
Расширенные примеры
1. Чтение части файла перед передачей

Код:

Пример php
<?
$handle = fopen('data.bin', 'rb');
// Пропустить первые 100 байт (заголовок)
fseek($handle, 100);
// Передать оставшуюся часть (тело данных)
$bytes = fpassthru($handle);
fclose($handle);
?>
2. Комбинирование с буферизацией вывода
Пример php
<?
ob_start();
$handle = fopen('large.log', 'r');
fpassthru($handle);
$content = ob_get_clean(); // Получить вывод в переменную
fclose($handle);
// Дальнейшая обработка $content
?>
3. Передача файла с докачкой (Resumable Download)
Пример php
<?
$file = 'video.mp4';
$handle = fopen($file, 'rb');
$size = filesize($file);
$start = 0;
$end = $size - 1;

if (isset($_SERVER['HTTP_RANGE'])) {
    // Обработка заголовка Range
    preg_match('/bytes=(\d+)-(\d*)/', $_SERVER['HTTP_RANGE'], $matches);
    $start = intval($matches[1]);
    if (!empty($matches[2])) {
        $end = intval($matches[2]);
    }
    header('HTTP/1.1 206 Partial Content');
    header("Content-Range: bytes $start-$end/$size");
    fseek($handle, $start);
    $length = $end - $start + 1;
    header('Content-Length: ' . $length);
    // Читаем и передаем только нужный диапазон
    echo fread($handle, $length); // fpassthru не подходит, т.к. передаст до EOF
} else {
    header('Content-Length: ' . $size);
    fpassthru($handle); // Передаем весь файл
}
fclose($handle);
?>
4. Использование с потоковыми контекстами
Пример php
<?
// Чтение удаленного файла по HTTP
$context = stream_context_create(['http' => ['method' => 'GET']]);
$handle = fopen('http://example.com/file.pdf', 'r', false, $context);
if ($handle) {
    header('Content-Type: application/pdf');
    fpassthru($handle);
    fclose($handle);
}
?>

PHP fpassthru function comments

En
Fpassthru Output all remaining data on a file pointer