readfile()
In PHP, the readfile() function is used to read the contents of a file and output it to the browser. It is a convenient way to display the contents of a file
Introduction
The PHP readfile() function reads a file and writes it straight to the output buffer, then returns the number of bytes it read. Because it streams the file directly to output instead of holding the whole thing in a PHP variable, it is the most memory-efficient way to send a file to the browser — which is exactly why it is the standard tool for file downloads.
This chapter covers the syntax and parameters of readfile(), what it returns, how it differs from related functions like file_get_contents() and fread(), and how to use it safely for displaying and downloading files.
Syntax
readfile(
string $filename,
bool $use_include_path = false,
?resource $context = null
): int|false| Parameter | Description |
|---|---|
$filename | Path (or URL, if allow_url_fopen is on) of the file to read and output. |
$use_include_path | If true, PHP also searches the include_path for the file. Defaults to false. |
$context | An optional stream context resource (created with stream_context_create()). |
Return value: the number of bytes read, or false on failure. Always check the return value rather than ignoring it, because a missing file emits a warning and still sends a partial (often empty) response.
How readfile() works
When you call readfile(), PHP opens the file, copies its bytes to the output buffer in chunks, and sends them to the client. The full contents are never loaded into a PHP string, so memory usage stays low even for multi-gigabyte files. The trade-off: you get no chance to transform the data — what comes out is a byte-for-byte copy of the file.
readfile() vs. the alternatives
Choosing the right function matters:
readfile()— stream a file directly to output. Best for downloads and serving raw files. No return string, just bytes-sent count.file_get_contents()— read the whole file into a string so you can modify, search, or store it. Uses memory proportional to file size.fopen()+fread()— open a handle for fine-grained, position-based reading; use when you need to read in controlled chunks or seek.highlight_file()— output a file with PHP syntax highlighting (for showing source code).
Rule of thumb: if you only need to send the file, use readfile(); if you need to process the file, read it into a variable instead.
Examples
Example 1: Displaying a text file
<?php
readfile('example.txt');This sends the contents of example.txt straight to the browser. With no Content-Type header set, the server's default applies (usually text/html).
Example 2: Checking the return value
readfile() returns the byte count, which is handy for logging or error handling:
<?php
$bytes = readfile('example.txt');
if ($bytes === false) {
http_response_code(404);
echo 'File not found.';
}Example 3: Forcing a download
To make the browser download a file instead of rendering it, send the right headers before any output, then call readfile():
<?php
$file = 'report.pdf';
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;Content-Type: application/octet-streamtells the browser this is a binary download.Content-Disposition: attachment; filename="..."triggers the "Save As" dialog and sets the suggested name.Content-Lengthlets the browser show an accurate progress bar.
The headers come from the header() function and must be sent before the function outputs any bytes — otherwise you get a "headers already sent" error.
Common gotchas
- Never pass unsanitized user input as
$filename. A value like../../etc/passwdwould let an attacker read arbitrary files (a path-traversal attack). Whitelist allowed files or run the path throughbasename()and confine it to a known directory. - No output before the headers. Even a stray space or BOM before
<?phpcounts as output and breaksContent-Disposition. - Clear output buffering for large files. If output buffering is enabled, the file can still be buffered in memory. Call
ob_end_clean()(orflush()) beforereadfile()when streaming very large files. - Reading remote URLs requires
allow_url_fopento be enabled inphp.ini.
Conclusion
readfile() is PHP's go-to function for sending a file to the client with minimal memory overhead: it streams bytes straight to output and returns the number of bytes sent. Use it for downloads and raw file serving, pair it with header() for downloads, validate the filename to avoid path-traversal attacks, and reach for file_get_contents() instead whenever you actually need the file's contents in a variable.