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文件损坏的主要内容,如果未能解决你的问题,请参考以下文章