I have a force-download script that produces good results with PDF and plain text, and is semi-OK with ZIP archives (they work in Windows, not in Linux). However, application files and images all fail. These make up the vast majority of the files I must handle. Zipping all downloads, as I've seen suggested on similar topics here, is not an option.
The failing files download to their full size, and are written to disk under the correct name. Attempts to open them result in a error message, which differs between types. Comparing downloaded files to their originals in hexdump, I can see that the script inserts the following characters at the start of each downloaded file:
ef bb bf
The downloaded file then reproduces the original until it stops at its specified size - so the original's last 6 characters are always missing.
Unfortunately I know nothing about how binary files are made up, what these characters might mean, or how/why the script is inserting them.
This is the script as-is:
$file = '94.ppt';
$path = $_SERVER['DOCUMENT_ROOT']."/relative/path/";
$full_path = $path.$file;
if ($fd = fopen ($full_path, "r")) {
$fsize = filesize($full_path);
$path_parts = pathinfo($full_path);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
head开发者_StackOverflower("Content-type: application/pdf");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
break;
case "txt":
header("Content-type: text/plain");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
break;
case "jpg":
header("Content-type: image/jpeg");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
break;
case "ppt":
header("Content-Type: application/vnd.ms-powerpoint");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Content-Transfer-Encoding: binary");
header("Content-length: $fsize");
header("Cache-control: private");
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;
The development system is PHP 5.3.2-1 on Apache 2.2.14 (Ubuntu). The production host is PHP 5.2.9 on Apache 2.0.63 (some type of Linux).
Your PHP script file seems to be encoded in UTF-8 with BOM that is right at the begin of the file before the opening <?php
delimiter. These bytes are sent before your actual output and thus corrupting your data.
You just need to remove it and configure your editor not to use the BOM for UTF-8.
EF BB BF
is the standard UTF-8 byte order mark. Some people have reported that this happens when some of your PHP files that you include in the script are UTF-8 encoded; some versions of PHP react to this by sending out the UTF-8 byte order marker. The link above suggests calling ob_start()
at the beginning of the script and ob_end_clean()
before you start pushing out the contents of your file -- this way the byte order marker gets caught in the output buffer.
Also, you could simply use fpassthru
to pipe your file to the output instead of reading and writing in a loop.
EF BB BF
is the UTF-8 encoding Byte Order Mark (BOM). I suspect there is some configuration option to turn off the BOM.
Edit: File editors should allow you to turn off the BOM when saving an file in relevant character encodings (e.g. UTF-8).
精彩评论