PHP强制下载.xlsx文件损坏

Posted

技术标签:

【中文标题】PHP强制下载.xlsx文件损坏【英文标题】:PHP force downloading .xlsx file corrupt 【发布时间】: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++ 说两个文件都匹配! 【参考方案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");

【讨论】:

不过,这不是 .xlsx 的 MIME 类型。 ***.com/a/4212908/206403 这也没什么区别。

以上是关于PHP强制下载.xlsx文件损坏的主要内容,如果未能解决你的问题,请参考以下文章

强制下载提示php损坏文件

节点在下载后写入损坏的.xlsx文件

下载xlsx文件打开一直提示文件已损坏

强制下载文件损坏的标题错误?

在 vue 项目中使用 blob 和 FileSaver.js 下载 excel(.xlsx) 已损坏

xlsx文件损坏如何修复(xls文件损坏怎么修复)