Fpassthru: примеры (PHP)
fpassthru(resource $stream): intФункция fpassthru используется для вывода оставшейся части данных из файлового указателя непосредственно в буфер вывода, обычно в браузер или консоль. Она читает данные с текущей позиции указателя до конца файла (EOF) и отправляет их. После выполнения указатель устанавливается в конец файла.
Функция принимает один обязательный параметр:
- $stream (resource) — файловый указатель, полученный с помощью функций типа
fopen(). Указатель должен быть открыт для чтения.
В случае успеха функция возвращает количество прочитанных и переданных байтов. В случае ошибки возвращается false.
Функция часто применяется для потоковой передачи бинарных файлов (например, изображений, PDF) напрямую клиенту без загрузки всего файла в память скрипта. Это полезно для уменьшения потребления памяти при отдаче больших файлов.
Код:
<?
$handle = fopen('example.txt', 'r');
if ($handle) {
$bytes = fpassthru($handle);
fclose($handle);
echo "\nПередано байт: $bytes";
}
?>Предполагая, что example.txt содержит текст 'Привет, мир!', результат:
Привет, мир! Передано байт: 13
Код:
<?
$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.
Выводит содержимое файла напрямую. Не требует предварительного открытия файлового указателя. Более удобна для простых случаев, когда не нужен контроль над потоком.
Копирует данные из одного потока в другой. Позволяет передавать данные между любыми потоками (например, из файла в сокет) с указанием длины копируемых данных.
Чтение файла блоками и вывод через 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)Создание читаемого потока и передача в ответ.
const fs = require('fs');
const readStream = fs.createReadStream('file.txt');
readStream.pipe(res); // res - объект ответа HTTPFpassthru в MySQL
Прямого аналога нет, но для вывода содержимого файла в виде строки можно использовать LOAD_FILE().
SELECT LOAD_FILE('/path/to/file.txt') AS file_content;В PHP fpassthru работает с уже открытым ресурсом потока, в то время как аналоги в других языках часто объединяют открытие и передачу или используют потоковые API.
<?
$handle = fopen('file.txt', 'r');
fclose($handle);
$result = fpassthru($handle); // Warning: ...
?>Warning: fpassthru(): supplied resource is not a valid stream resource
<?
$handle = fopen('image.jpg', 'rb');
fpassthru($handle);
header('Content-Type: image/jpeg'); // Ошибка: заголовки уже отправлены
?><?
$handle = fopen('file.txt', 'w'); // Открыт для записи
fpassthru($handle); // Не сработает
?>В PHP 8 не было внесено значительных изменений в поведение функции fpassthru. Важным общим изменением в PHP 8 является более строгая типизация — передача неправильного типа аргумента теперь вызовет TypeError вместо предупреждения.
<?
fpassthru('not_a_resource');
?>TypeError: fpassthru(): Argument #1 ($stream) must be of type resource, string given
Код:
<?
$handle = fopen('data.bin', 'rb');
// Пропустить первые 100 байт (заголовок)
fseek($handle, 100);
// Передать оставшуюся часть (тело данных)
$bytes = fpassthru($handle);
fclose($handle);
?><?
ob_start();
$handle = fopen('large.log', 'r');
fpassthru($handle);
$content = ob_get_clean(); // Получить вывод в переменную
fclose($handle);
// Дальнейшая обработка $content
?><?
$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);
?><?
// Чтение удаленного файла по 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);
}
?>