jimmyjambles
jimmyjambles

Reputation: 1670

PHP readfile() adding extra bytes to downloaded file

I am trying to troubleshoot an issue I am having with downloading a "zip" file from a php script. It seems that when I download the file using the following code, the downloaded file has an extra 0A09 appended to the beginning of the file, causing winzip to throw a corruption error.

<?php
$pagePermissions = 7;
require_once ('util/check.php');
require_once ('util/file_manager.php');

$file_manager = new FileManager();

if ($_SERVER['REQUEST_METHOD'] == "GET") {
if (isset($_GET['q']) && $_GET['q'] == 'logout') {
    //require_once ('util/users.php');
    //$userdata = new Userdata();
    $userdata -> kill_session();
    header("Location: download.php");
    exit ;
}

if (isset($_GET['q']) && $_GET['q'] == 'fetch') {
    if (isset($_GET['name'])) {
        @apache_setenv('no-gzip', 1); 
        header("Content-length: " . filesize('upload/' . $_GET['name'])); 
        header('Content-type: application/zip');
        //header("Content-Disposition: attachment; filename=\"{$_GET['name']}\" ");
        header("Content-Disposition: attachment; filename={$_GET['name']}");
        header('Content-Transfer-Encoding: binary');

        readfile('upload/' . $_GET['name']);
        exit();
    }
}

}
?>

Any help would be greatly appreciated, the file downloads fine through a direct link, the appended 2 bytes to the beginning of the file occurs only thorough this code. Thanks in advance

Upvotes: 4

Views: 15901

Answers (6)

Michael Chaplin
Michael Chaplin

Reputation: 1

I had a similar issue with blank space at the start of an image file.

I suspect my issue was caused by blank space before opening

What worked for me was:

@ob_start('');  //@ supresses a warning  
//header entries
ob_end_clean();
ob_clean();
readfile($file);

Upvotes: 0

user3820294
user3820294

Reputation: 31

I had same problem So I used this headers and I got my solution.

    $filename = ABSPATH.'/wp-content/summary/user_content/'.trim($file);
    header('Pragma: public');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Content-Description: File Transfer');
    header('Content-Type: text/text');
    header('Content-Disposition: attachment; filename="'.$file.'"');
    header('Content-Transfer-Encoding: binary');
    header('Cache-Control: max-age=0');
    readfile($filename);
    exit;

Upvotes: 0

Nifty
Nifty

Reputation: 174

Sorry for late reply.....

i don't know i am right until you vote this.....

edit your code as :

ob_start(""); 
//instead of ob_start(); with out a null callback 

and

ob_end_clean();  //at the end , Note : "important" add instead of ob_end_flush()

ie;

ob_start("");
//header           
ob_end_clean();

Upvotes: 1

From Orbonia
From Orbonia

Reputation: 676

I had a similar problem in Joomla (2.5), using readfile to pass back Excel (.xls) files to the user.

I also noticed that the text and xml files also had some code inserted at the begining, but nearly ignored it because xml & text readers tended to open the files still.

I decided to try Yanick's suggestions (rather than playing with server compression options), simply flushing the buffer before readfile:

ob_clean();   // discard any data in the output buffer (if possible)
flush();      // flush headers (if possible)

Hey presto, it worked. I'm suggesting this as an alternative answer: to highlight the root cause, show it can fix a Joomla issue and because I had a mixture of binary and text returns.

Just to add (apologies if this is obvious!) - the mime type setting worked fine:

$document = JFactory::getDocument();
$document->setMimeEncoding($mimetype);

I did not even need to set 'Content-Transfer-Encoding: binary' when the mime type was to application/octet-stream.

Upvotes: 0

tchen
tchen

Reputation: 2242

I ran into a similar issue today related to readfile(). It turns out my php.ini file has output compression enabled and that was messing up the flash module trying to retrieve the file. (I guess it couldn't handle it.)

All I had to do was the turn off the compression in the php.ini file:

zlib.output_compression = off

Or alternatively, in your script:

<?php ini_set('zlib.output_compression', 'Off'); ?> 

Just want to share this in case someone else was having trouble receiving files from a readfile() output.

Upvotes: 0

Yanick Rochon
Yanick Rochon

Reputation: 53536

Remove the last ?> and check that your opening tag is on the very first line, at the very first character of your scripts. PHP files do not have to end with end tags. The reason why your downloaded files contain a (or more) \r\n is because PHP will directly echo (output) anything outside of <?php ?>. Usually, if you script does not echo HTML, you will omit the closing PHP tag as it is not mandatory and, IMO, yields more trouble than anything else.

** Edit **

If you read the PHP manual for readfile, you have a useful example, pretty much the code you have in your question, less two lines of code :

@apache_setenv('no-gzip', 1); 
header("Content-length: " . filesize('upload/' . $_GET['name'])); 
header('Content-type: application/zip');
//header("Content-Disposition: attachment; filename=\"{$_GET['name']}\" ");
header("Content-Disposition: attachment; filename={$_GET['name']}");
header('Content-Transfer-Encoding: binary');

// add these two lines
ob_clean();   // discard any data in the output buffer (if possible)
flush();      // flush headers (if possible)

readfile('upload/' . $_GET['name']);
exit();

If you still have a problem after that, then the problem might not be with your PHP code.

Upvotes: 25

Related Questions