PHP readfile()为下载的文件添加额外的字节

时间:2011-11-07 19:37:11

标签: php

我正在尝试解决从php脚本下载“zip”文件时遇到的问题。似乎当我使用以下代码下载文件时,下载的文件在文件的开头附加了额外的0A09,导致winzip抛出损坏错误。

<?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();
    }
}

}
?>

任何帮助都将非常感激,文件通过直接链接下载正常,文件开头附加的2个字节仅通过此代码发生。 提前致谢

6 个答案:

答案 0 :(得分:22)

删除最后一个?>并检查您的开始标记是否位于脚本的第一个字符的第一行。 PHP文件必须以结束标记结束。您下载的文件包含(或更多)\r\n的原因是因为PHP将直接回显(输出)<?php ?>之外的任何内容。通常,如果你的脚本没有回显HTML,你将省略关闭的PHP标记,因为它不是强制性的,IMO会产生比其他任何东西更多的麻烦。

** 修改 **

如果您阅读了readfile的PHP手册,那么您有一个有用的示例,几乎是您在问题中的代码,少了两行代码:

@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();

如果之后仍有问题,那么问题可能与您的PHP代码无关。

答案 1 :(得分:1)

很抱歉迟到的回复.....

我不知道我是对的,直到你投了这个......

将您的代码编辑为:

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

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

即;

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

答案 2 :(得分:0)

我今天遇到了与readfile()相关的类似问题。事实证明我的php.ini文件已启用输出压缩,并且正在弄乱试图检索文件的闪存模块。 (我想它无法处理它。)

我所要做的只是关闭php.ini文件中的压缩:

zlib.output_compression = off

或者,在您的脚本中:

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

只是想分享一下,以防其他人在从readfile()输出接收文件时遇到问题。

答案 3 :(得分:0)

我在Joomla(2.5)中遇到了类似的问题,使用readfile将Excel(.xls)文件传回给用户。

我还注意到文本和xml文件也在开头插入了一些代码,但几乎忽略了它因为xml&amp;文本阅读器仍倾向于打开文件。

我决定尝试Yanick的建议(而不是使用服务器压缩选项),只需在readfile之前刷新缓冲区:

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

嘿presto,它有效。我建议将此作为一个替代答案:突出根本原因,显示它可以修复Joomla问题,因为我有二进制和文本返回的混合。

添加(道歉,如果这很明显!) - mime类型设置工作正常:

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

当mime类型为application / octet-stream时,我甚至不需要设置'Content-Transfer-Encoding:binary'。

答案 4 :(得分:0)

我有同样的问题所以我使用了这个标题,我得到了我的解决方案。

    $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;

答案 5 :(得分:0)

在图像文件开始处的空白处,我遇到了类似的问题。

我怀疑我的问题是由打开前的空白引起的

对我有用的是:

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