2

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?

multimediaxp
  • 9,348
  • 13
  • 49
  • 80

1 Answers1

2

I think you are missing out an important header header("Content-length: $size") here. You can use int 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 the Content-length easily by setting up the Curl 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!

Community
  • 1
  • 1
SyntaX
  • 2,090
  • 17
  • 30
  • The problem is that the file is external from the server, I don;t think I can read the size like that. Another question why if i don't specify the size the file ends up being bigger? – multimediaxp Nov 25 '15 at 05:18
  • 1
    I have updated the answer, hopefully will resolve your problem. Please check out the links. Using `curl` should resolve your issue! – SyntaX Nov 25 '15 at 05:30
  • Great thanks a lot, I modified your answer and added the final code that solves the question. Thanks a lot! – multimediaxp Nov 27 '15 at 22:22