【问题标题】:PHP force downloading .xlsx file corruptPHP强制下载.xlsx文件损坏
【发布时间】:2012-12-05 23:12:57
【问题描述】:

我正在开发一个允许教师上传文档和学生下载文档的网站。但是,有一个问题。 Microsoft Word (.docx) 文件下载完美,但在下载 excel (xlsx) 文件时,excel 会出现“此文件已损坏且无法打开”对话框。对此的任何帮助将不胜感激!

我的下载代码如下:

case 'xlsx':

    header('Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Pragma: no-cache');
    readfile('./uploads/resources/courses/' . $filename);

break;

【问题讨论】:

  • 输出任何空格,例如在打开标签之前?是否有任何警告/通知,这些会使文件损坏。从 FTP 源下载文件并打开它以验证原始文件没有损坏。
  • 下载的文件是什么样的?是空的吗?它被切断了吗?在后一种情况下,您可以尝试发送 Content-Length 标头。另一个问题可能是下载时间过长并且 PHP 会引发超时。使用set_timeout() 提高超时时间。
  • switch 块之后会发生什么?通常你在打电话给readfile之后exit;
  • 空白不会影响服务器上的文件.... 它是空白或 BOM 或脚本中的回显消息/警告/错误与文件一起发送到 php://output本身就是最可能的原因
  • 现在真的很混乱! Notepad++ 说两个文件都匹配!

标签: php header download readfile


【解决方案1】:

可能这是非常Windows 提供的误导性信息,与代码、Excel 库或服务器无关,文件本身是正确的。 Windows 阻止打开从 Internet 下载的某些文件(如 .xlsx),而不是询问您是否要打开不安全的文件,它只是写该文件已损坏。在 Windows 10 中,需要右键单击文件并选择“Unblock”(您可以在此处阅读更多信息:https://winaero.com/blog/how-to-unblock-files-downloaded-from-internet-in-windows-10/

【讨论】:

    【解决方案2】:

    我有这个问题,是BOM

    如何注意

    unzip:用 unzip 检查输出文件,我在第二行看到了警告。

    $ unzip -l file.xlsx 
    Archive:   file.xlsx
    warning file:  3 extra bytes at beginning or within zipfile
    ...
    

    xxd(十六进制查看器):我通过以下命令看到了前 5 个字节

    head -c5 file.xlsx | xxd -g 1
    0000000: ef bb bf 50 4b                             PK...
    

    注意前 3 个字节 ef bb bf 是 BOM!

    为什么?

    可能是带有 BOM 的 php 文件或库的先前输出。

    你必须找到带有 BOM 的文件或命令在哪里,就我而言,现在我没有时间找到它,但我用输出缓冲区解决了这个问题。

    <?php
    ob_start();
    
    // ... code, includes, etc
    
    ob_get_clean();
    // headers ...
    readfile($file);
    

    【讨论】:

      【解决方案3】:

      尝试添加额外的标题

      header('Content-Length: ' . filesize('./uploads/resources/courses/' . $filename));
      

      【讨论】:

        【解决方案4】:

        尝试:

        <?
        //disable gzip
        @apache_setenv('no-gzip', 1); 
        //set download attachment
        header('Content-Disposition: attachment;filename="filename.xlsx"');
        //clean the output buffer 
        ob_clean(); 
        //output file
        readfile('filepath/filename.xlsx');
        //discard any extra characters after this line
        exit; 
        ?>
        

        【讨论】:

          【解决方案5】:

          无论扩展名如何,这在我的本地 xampp 设置上都可以正常工作,因此从我的角度来看,除非我遗漏了什么,否则不需要 case 语句

          我已经测试过 docx、accdb、xlsx、mp3,任何东西......

          $filename = "equiv1.xlsx";
          
          header('Content-type: application/octet-stream');
          header('Content-Disposition: attachment; filename="' . $filename . '"');
          header('Content-Transfer-Encoding: binary');
          header('Expires: 0');
          header('Pragma: no-cache');
          

          【讨论】:

          • 谢谢,但是给了我一个更长的错误信息,关于它的格式不正确!
          • 您如何存储文件?你改变他们的名字或扩展名吗?如果您尝试打开一个您确定它是 xlsx 的文件,它会给出该错误,好的,但是您首先如何将文件保存在您的服务器上?
          • 好的,用户上传文件,脚本采用$_FILES['resource']['name'] 删除扩展名,用下划线替换空格,添加一个四位数字并添加扩展名。然后使用move_uploaded_file() 将其从 tmp_name 移动到新路径。但是,当我进入服务器上的上传路径文件夹时,新上传的文件可以正常打开,只有在下载时才会中断。
          • 我已经删除了文件名的处理,现在它只是将原始文件存储在文件夹中。我删除了开关块,但它已恢复为简短的错误消息。
          • 新代码就像你写的那样简单,但是,我认为文件的实际路径没有在任何地方说明。文件名将是“excel1.xlsx”,但这不是路径...
          【解决方案6】:

          试试这个:

          header("Content-Disposition: attachment; filename=\"$filename\"");
          header("Content-Type: application/vnd.ms-excel");
          

          【讨论】:

          猜你喜欢
          • 2013-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多