fpassthru
Reads a file handle from its current position to EOF and writes it straight to output.
fpassthru(resource $stream): int- Added in PHP 4.0.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$stream | resource | An open file pointer from fopen() or fsockopen() that has not been closed. |
Return value
intThe number of characters read from the stream and passed to output.
Errors
Throws a TypeError if the argument is not a valid open stream resource.
fpassthru takes an already-open stream and writes everything from the current position to the end straight to output. It streams in chunks rather than building a string, so memory usage stays flat no matter how large the file is.
When to reach for it
- Serving a file download after you have already opened the handle — to check a header, verify a magic number, or take a lock.
- Sending only the tail of a file, by
fseek-ing first. - Draining a socket or process stream to the browser.
fpassthru or readfile?
If all you have is a path and you want the whole file, readfile() is the better choice — it does the fopen for you and returns the same byte count. Reach for fpassthru when you already hold a handle, or when you deliberately want to skip part of the file.
What trips people up
It starts from the current file position, not the beginning. If you have read a header or written to the handle, call rewind($fh) first or you will silently send a truncated file. This is the number one cause of "my download is missing its first bytes".
In a web context, send your Content-Type and Content-Length headers before calling it, and consider ob_end_flush() so output buffering does not undo the memory benefit. The handle is left open — fclose it yourself.
Example
When to use it
- Serve a protected download after checking permissions, without loading the file into memory.
- Send only the last N bytes of a log file by fseek-ing before the passthru.
- Pipe an in-memory stream you just built straight to the response body.
Frequently asked questions
What is the difference between fpassthru and readfile?
`readfile()` takes a path, opens it, and dumps the whole file; `fpassthru()` takes an already-open handle and dumps from the current position. Use `readfile` when you have just a filename and want everything.
Why is my fpassthru output missing the start of the file?
Because the file pointer was not at the beginning — any earlier `fgets`, `fread` or `fwrite` moved it. Call `rewind($fh)` before `fpassthru`.
Does fpassthru load the whole file into memory?
No, it streams the data in chunks, so memory usage stays constant regardless of file size. That is its main advantage over `echo file_get_contents($path)`.
More examples
Rewind before passing through
The full 31-byte file is emitted, header included, because `rewind()` reset the position after the inspection read. Drop the rewind and the output starts at `payload one`.
<?php
file_put_contents('data.txt', "HEADER\npayload one\npayload two\n");
$fh = fopen('data.txt', 'rb');
$header = trim(fgets($fh));
echo "checked header: $header\n";
rewind($fh); // without this the header is missing
$n = fpassthru($fh);
fclose($fh);
echo "--\nsent $n bytes\n";
unlink('data.txt');Sending only the tail of a file
Only the final stretch of the file is printed and the count reports 26 bytes. Combining `fseek` with `fpassthru` gives you a cheap tail without reading the earlier megabytes.
<?php
$lines = '';
for ($i = 1; $i <= 20; $i++) { $lines .= "log line $i\n"; }
file_put_contents('tail.log', $lines);
$fh = fopen('tail.log', 'rb');
fseek($fh, -26, SEEK_END); // jump near the end
$n = fpassthru($fh);
fclose($fh);
echo "--\n$n bytes from the tail\n";
unlink('tail.log');Passing through an in-memory stream
The two written rows appear in the output followed by a count of 22. Because the stream lives in memory, this pattern lets you build a response body and flush it without a temp file.
<?php
$fh = fopen('php://memory', 'r+');
fwrite($fh, "generated,report\n");
fwrite($fh, "1,ok\n");
rewind($fh);
$bytes = fpassthru($fh);
fclose($fh);
echo "--\n$bytes bytes emitted, nothing written to disk\n";
Discussion