PHP强制下载.xlsx文件已损坏

PHP强制下载.xlsx文件已损坏,php,header,download,readfile,Php,Header,Download,Readfile,我正在开发一个网站,允许老师上传文件,学生下载。然而,有一个问题。Microsoft Word(.docx)文件下载非常完美,但在下载excel(xlsx)文件时,excel会显示“此文件已损坏且无法打开”对话框。在此方面的任何帮助都将不胜感激 我的下载代码如下: case 'xlsx': header('Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); head

我正在开发一个网站,允许老师上传文件,学生下载。然而,有一个问题。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;
试试这个:

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

无论扩展如何,这在本地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');
尝试:


尝试添加额外的标题

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

我有这个问题,是我的错

如何注意它 解压:通过解压检查输出文件,我在第二行看到一条警告

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

这可能是Windows提供的非常具有误导性的信息,与代码、Excel库或服务器无关,而且文件本身是正确的。Windows会阻止打开从Internet下载的一些文件(如.xlsx),而不是询问您是否要打开不安全的文件,而是写入文件已损坏。在Windows 10中,需要右键单击该文件并选择“取消阻止”(您可以在此处阅读更多信息,例如:)

在打开标记之前是否输出任何空白?是否存在任何警告/通知,这些警告/通知将导致文件损坏。从FTP源下载文件并打开以验证原始文件未损坏。下载的文件是什么样子的?是空的吗?它被切断了吗?在后一种情况下,您可以尝试发送
内容长度
标题。另一个问题可能是下载时间太长,PHP会引发超时。使用
set\u timeout()
来提高超时时间。切换
块后会发生什么?通常你
退出
调用
readfile
后。空白不会影响服务器上的文件。。。。它是来自脚本的空白、BOM表或回显消息/警告/错误发送到的php://output 除了文件本身之外,现在最有可能造成混乱的是它!记事本++说两个文件都匹配!不过,这不是
.xlsx
的MIME类型。这也没什么区别。谢谢,但是给了我一条更长的错误消息,关于它的格式不正确!你如何存储你的文件?你会改变他们的名字或分机吗?如果你试图打开一个文件,你肯定知道它是xlsx,它会给出错误,好吧,但是你首先要如何在你的服务器上保存文件呢?好吧,用户上传文件,脚本使用
$\u files['resource']['name']
删除扩展名,用下划线替换空格,添加四位数并添加扩展名。然后使用
move\u uploaded\u file()
将其从tmp\u名称移动到新路径。但是,当我进入服务器上的上载路径文件夹时,新上载的文件会正常打开,只有在下载时才会断开。我已经删除了对文件名的处理,现在它只是将原始文件存储在文件夹中。我删除了开关块,但它已恢复为短错误消息。新代码与您编写的代码一样简单,但是,我认为文件的实际路径没有在任何地方声明。文件名将为“excel1.xlsx”,但这不是路径。。。
<?php
ob_start();

// ... code, includes, etc

ob_get_clean();
// headers ...
readfile($file);