Download large files in PHP


Developers experience issues while downloading large files using PHP, there are no of possible things to cause issue, i.e incorrect headers for browsers or incorrect file streaming.

Lets see how the correct headers are passed and how the large files are streamed in chunks

Note: Best practice is to zip your file/contents.

Lets talk about headers

You need to send correct headers to browser

//path to your orignal file
$file = "/home/xyz/file-to-download.zip";

//will be downloaded as "documents.zip" to users, you can use original name as well.
$downloadName = "documents.zip";

//telling browser that the content type is zip file
header('Content-Type: application/zip');

//telling browser about correct length of file in bytes
header('Content-Length: ' . filesize($file));

//tell browser to download it
header('Content-Disposition: attachment; filename="' . $downloadName . '"');

//handle caching	
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false);

//tell browser the encoding of file
header('Content-Transfer-Encoding: binary'); 

Once header part is done we move to reading file in chunks of bytes and sending those chunks instantly to browser, in other words streaming the file.

//set download speed in bytes
$bitrate = 1024; 
//1024 bytes = 1Kb

//how much bytes to read in a chunk
$chunkSize = $bitrate * 1024;

//open file for reading in binary mode
$handle = fopen($file, 'rb');

//read file chunks by chunk and send output to browser until end of file is not reached
while (!feof($handle)) {
    //read chunk of a file
    echo fread($handle, $chunkSize);

    //send an application-initiated buffer
    ob_flush();

    //usually FastCGI has a socket buffer on its own so use flush() to send the current content.
    flush();
}

fclose($handle);

You can use $bitrate variable to control the speed of download for example

//set speed to 100kb
$bitrate = 100; 
Advertisements

2 thoughts on “Download large files in PHP

  1. Rodrigo says:

    Hi, this code works like a charm, but after download a 11GB file, it warns me the file is corrupted.
    I tested the same file before upload to server, and it’s totally fine.
    Do you have any idea how to solve it?
    Thanks in advance.
    Rodrigo

  2. Tofeeq says:

    Have you tested it with a smaller file on your server?
    Here are steps to test.
    1. Test it with smaller file if that is also corrupt then download that file using ftp and see if that is fine. If file downloaded by ftp is also corrupt that means there is something wrong at file uploading.
    2. If the file downloaded by ftp seems fine then there might be spaces in download script, you can use ob_end_clean to clean up buffer before starting download.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s