Handling large files is a common task for web developers. However, if not done properly, it can lead to high memory usage and slow performance. In this tutorial, we will look at how to stream large files to the browser in a memory-efficient way using PHP.
Prerequisites
- Basic knowledge of PHP
- An active PHP development environment
Step 1: File Streaming Basics
Before we dive into the code, let's first understand what file streaming is. When you open a file in PHP with fopen()
, you can read it line by line or character by character with fgets()
or fgetc()
, instead of loading the entire file into memory. This is known as file streaming.
Step 2: Setting Up the PHP Script
Let's create a new PHP script, download.php
. In this script, we will:
- Open the file we want to stream.
- Read a portion of the file and output it to the browser.
- Repeat step 2 until the entire file has been read and sent.
Here's the code:
<?php
$file = 'path/to/your/largefile.pdf';
// Make sure the file exists
if (!file_exists($file)) {
die('File not found.');
}
// Set headers to tell the browser to download the file
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Length: ' . filesize($file));
// Open the file in binary mode
$fp = fopen($file, 'rb');
// Output the file
while (!feof($fp)) {
// Read and output a chunk of the file
echo fread($fp, 8192);
// Flush the output buffer to free up memory
ob_flush();
flush();
}
// Close the file
fclose($fp);
exit;
In the above code, we use fopen()
to open the file and fread()
to read a chunk of 8192 bytes at a time (which is approximately 8KB). We then output this chunk using echo
and flush
the output buffer to free up the memory used. This process repeats until the end of the file (feof($fp)
returns true
).
In this tutorial, you've learned how to stream large files to the browser in a memory-efficient way using PHP. This method is very useful when dealing with large files that could otherwise consume significant server memory and lead to performance issues. Always remember to close any open file handles and flush the output buffer to free up memory.
Top comments (3)
I have added output buffer settings. ob_flush() seems to work, but still cannot
transfer 500Mg files.
Did not work:
Got error "PHP Notice: ob_flush(): failed to flush buffer. No buffer to flush in download.php on line 8"
$handle = fopen($file_path, 'rb');
if ($handle === false) {
die("Could not open file. Check access controls");
}
while (!feof($handle)) {
//@@@print(fread($handle, 1024*8));
echo fread($handle, 1024*8);
ob_flush();
flush();
}
$status = fclose($handle);
For simple reading whole file there is built-in function, which is already memory-safe php.net/manual/en/function.readfil...