ZIP downloads are bigger in size than they actually are on external server using PHP headers

735

We are hosting some heavy files that are advertised as free downloads on one of our sites. These files are on another server so in order to generate the download we execute this code:

header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type:application/octet-stream");
header("Content-Transfer-Encoding: binary"); 
header("Content-Disposition:attachment;filename='$fileName'");
readfile("http://mysiste.com/downloads/$fileName");

Where$fileName is the name of the zip files. Example: myfile.zip All works fine except that if myfile.zip is 8Mb on the server it will download as 16Mb! The craziest thing is that the file works fine and when unzipping the file all the files inside are complete and not corrupted.

I guess it has something to do with the headers and the transfer encoding as if the zip file looses the compression.

Any ideas?

165

Answer

Solution:

I think you are missing out an important headerheader("Content-length: $size") here. You can useint filesize (string $filename) to find the file size. Here is the API doc

<?php
$fileName = "downloaded.pdf"
$size = filesize($file);
header('Content-type: application/pdf');
header("Content-length: $size");
header("Content-Disposition: attachment; filename='$fileName'");
readfile($file);
?>

If the file is located in a remote server, you can GET theContent-length easily by setting up theCurl without actually downloading it. These stackoverflow threads should help you:

Reference credit: Content-length and other HTTP headers?

This is the code that would combine curl and PHP headers:

$url="http://mysite/downloads/$fileName";
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_HEADER, true); 
curl_setopt($ch, CURLOPT_NOBODY, true); // make it a HEAD request
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 
$head = curl_exec($ch);

$mimeType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
$size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
$path = parse_url($url, PHP_URL_PATH);
$filename = substr($url, strrpos($path, '/') + 1);

curl_close($ch); 

header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type:$mimeType");
header("Content-Disposition:attachment;filename='$fileName'");
header('Content-Length: '.$size);
readfile($url);

I hope this helps!

People are also looking for solutions to the problem: php - MySQL Query equivalent in CodeIgniter

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.