PHP:下载的二进制文件在结尾处获得一个额外的字节(0x0a)

PHP Version 5.2.17

I have the following PHP script for downloading a binary file:

<?php

$download_dir = '.';
$download_file = $_GET['get'];

$path = $download_dir.'/'.$download_file;

if(file_exists($path))
{
    $size = filesize($path);

    header('Content-Type: application/x-download');
    header('Content-Disposition: attachment; filename='.$download_file);
    header('Content-Length: '.$size);
    header('Content-Transfer-Encoding: binary');

    readfile($path);
}else{
    echo "<font face=$textfont size=3>";
    echo "<center><br><br>The file [<b>$download_file</b>] is not available for download.<br>";
}
?>

URL used to call this script:

http://myserver/cur/downloads/test.php?get=FooBar_Setup.exe

Downloading works but the downloaded file has an additional byte (0x0a) appended.
The headers of the response also show a Content-Length that is one byte larger than the size of the requested file:

HTTP/1.1 200 OK
Date: Mon, 05 Dec 2011 10:29:32 GMT
Server: Apache/2.2
Content-Disposition: attachment; filename=FooBar_Setup.exe
Content-Length: 1417689
Content-Transfer-Encoding: binary
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/x-download

The size of the file on the server is 1417688 bytes.

I have verified that filesize($path) returns the correct file size. It seems that PHP alters the Content-Length header with filesize($path)+1.
I see this behavior with two different files.

How can I get prevend PHP from appending 0x0a to the downloaded binary files?

You most likely have an extra blank line after the closing ?>, which is being echoed with the data. The closing ?> is always optional at the end of a PHP file. Leaving it out is a good practice to prevent this sort of problem.

The reason the Content-Length changes is because the HTTP server (or PHP?) is ignoring it and adding a new one to match the actual data response before it gets sent it to the browser, so I think you can just leave that out. (If you do manage to send data with the wrong Content-Length, I've found browsers can act very weird.)

You have a line break in your PHP script after the closing ?> tag. This is where the stray line break is coming from.

The best way to avoid this problem (which crops up a lot here on SO, by the way) is to not use the closing ?>. PHP does not require it, and it helps avoid this problem.

Try Adding exit after readfile:

//ob_clean();
//flush();
readfile($path);
exit;

or you can remove the ?> if there is only 1 block of php code in the current file:

<?php

$download_dir = '.';
$download_file = $_GET['get'];

$path = $download_dir.'/'.$download_file;

if(file_exists($path))
{
    $size = filesize($path);

    header('Content-Type: application/x-download');
    header('Content-Disposition: attachment; filename='.$download_file);
    header('Content-Length: '.$size);
    header('Content-Transfer-Encoding: binary');

    readfile($path);
    exit;

}else{
    echo "<font face=$textfont size=3>";
    echo "<center><br><br>The file [<b>$download_file</b>] is not available for download.<br>";
}

Compression can also cause extra bytes to show up in downloaded files. At the top of your script, add:

ini_set("zlib.output_compression", "off");

to disable it for that PHP script. Alternatively, or in addition, you may want to verify that your web server isn't also compressing your output for that script.