WebICT By Leo
WebICT By Leo

Reputation: 25

Php download script outputs corrupted file

I was building a file download Class for my CMS in PHP, at a time I noticed it outputs files in a different Encoding format. I tried with readfile, file_get_contents,fread but all seem to be doing the same thing. It"s like something that has to do with output buffering.

An example image file in png format I downloaded using the script seems to work after changing the Encoding using notepad++ from UTF to ASCII

These are the steps i've taken so far:

$mime = http::get_file_mime();
header('Pragma: public');   
header('Expires: 0');       
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private',false);
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Transfer-Encoding: binary');
header('Transfer-Encoding: binary');
header('Content-Description: File Transfer');
header('Content-Encoding: chunked');
header('Connection: closed');
@readfile($this->file);

I did fread:

$file = fopen($this->file,'r');
$read = fread($file,filesize($this->file));
print($read);

I did file_get_contents();

$read = file_get_contents($this->file);
print($read);

All of these steps sends the file to the download dialog. But it doesnt output the file as it is. And this affects any file i try to download with the script.

What am i doing wrong ?

Upvotes: 0

Views: 1545

Answers (2)

Ajay Makwana
Ajay Makwana

Reputation: 2372

Try running an ob_start() as the first thing in your script, write stuff, edit your headers and then ob_flush() and ob_clean() whenever you want your content to be sent to the user's browser.

This is worked for me..

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

Hope this helps..

Upvotes: 1

Olaf Dietsche
Olaf Dietsche

Reputation: 74008

The problem lies in the Content-Disposition header. This header is not really part of the HTTP protocol, see RFC 2616, 15.5 Content-Disposition Issues

Content-Disposition is not part of the HTTP standard, but since it is widely implemented, we are documenting its use and risks for implementors.

And later in section 19.5.1 Content-Disposition

The Content-Disposition response-header field has been proposed as a means for the origin server to suggest a default filename if the user requests that the content is saved to a file.
...
An example is

Content-Disposition: attachment; filename="fname.ext"

If this header is used in a response with the application/octet- stream content-type, the implied suggestion is that the user agent should not display the response, but directly enter a `save response as...' dialog.

Leaving out this header shows the contents of the sent file.

I have tested this with Firefox only, so other web browsers might behave different.

Upvotes: 0

Related Questions