Word / Excel文件从PHP下载时损坏
我正在建立一个简单的文件上传/文件下载功能到我的数据库中。 唯一复杂的部分是所有文件都需要使用我的花式嘘声加密方法进行加密。
所以我所做的是创建一个SQL条目,它存储如下内容:id_file,文件名,扩展名,大小,dateadded等
然后,一旦我获得了id_file,我将文件内容加密,然后将它们加密,然后将内容作为[id_file] .txt保存到我的服务器。
然后这里是再次下载文件的代码:
header("Pragma: public");
header('Content-Disposition: attachment;filename="'.$file['name'].'.'.$file['extension'].'"');
header('Cache-Control: max-age=0');
echo someFunctionIMadeForGettingAndDecryptingFileContents($_GET['id_file']);
exit;
非常简单的东西,并完全适用于所有文件类型,除了.docx和.xlsx。 当下载.docx或.xlsx文件时,Office给我一个错误,说“Word在”NAME OF FILE“中发现了不可读的内容。你想恢复本文件的内容吗?如果你相信源... bla bla”I then点击'是'。 它认为一点,文件打开就好了。 但显然,如果他们每次都会发生这样的错误,我不能让我的客户使用它。
我写的代码完美适用于所有其他文件类型。 即使.doc,.xls和.zip文件也能正常工作。
我的第一个想法是看标题。 我已经尝试了各种解决方案,如下所列的解决方案:
为什么我的下载文件一直在损坏或损坏? PHP下载excel文件变得腐败
那些不起作用。
我知道一个问题可能是在文件中添加了额外的填充或空白区域。 但是,如果我上传.txt文件,然后再次下载...我可以看到没有任何额外的被添加。
如果我MD5原始文件(good.docx)和原始文件(bad.docx)的下载版本,散列值是不同的。
如果我将good.docx更改为good.zip并解压缩存档。 然后对bad.docx执行相同的操作。 然后MD5这两个目录,哈希是相同的。 我把每个文件散列在good.zip和bad.zip中,每个文件散列都是一样的。
另外要注意的是,在我的服务器上的其他地方,我使用PHPWord和PHPExcel动态生成Office文件,并且这些文件都可以很好地下载。 我用于PHPExcel的标头/代码是:
header("Pragma: public");
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="'.$filename.'.xlsx"');
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');
exit;
(是的,我试过在上面的其他代码中使用“Content-Type”标题,但这没有帮助。)
我也尝试将文件保存在我的服务器上,下载并打开它。 在经历这个过程时,我会遇到同样的错误。 这是我用来做的代码:
$f=fopen("/myPath/temp.docx","w");
fwrite($f,someFunctionIMadeForGettingAndDecryptingFileContents($_GET['id_file']));
fclose($f);
exit;
我试过创建一个名为“blank.docx”的空白Word文件。 然后创建它,而不是保存一个新文件的功能....它将用解密后的文件内容替换blank.docx的内容。 但是,在这个过程之后下载blank.docx时,我得到的都是一样的错误,但最终会打开。 没有任何原始位于blank.docx的文件属性(如Template:Normal.dotm)在所提供的修改过的blank.docx中。
我正在使用Office 2007
UPDATE
这是一个链接,用于下载文件的好(原始)版本:http://empowerdb.org/good.docx
下面是一个链接,用于下载该文件的错误(已处理)版本:http://empowerdb.org/bad.docx
解
正如Llama先生指出的那样,我的加密功能正在削减一些额外的空字节。 但事实证明,罪魁祸首并不像你想象的那么明显。 这是我的加密:
trim(base64_encode(IV.mcrypt_encrypt(MCRYPT_RIJNDAEL_128,ENCKEY,$contents,MCRYPT_MODE_CBC,IV)))
问题不在于trim()或base64_encode()。 这是与mcrypt函数。 我解决这个问题的方式是在传递我的文件内容以获得加密之前,我做了另一个base64_encode()。 所以像这样...
$file_contents_encrypted=base64_encode(myEncryptionFunction($file_contents));
当然,在解密时也是相反的。
base64_encode在技术上运行两次。 但是我可以看到在这种情况下需要在mcrypt之前运行,因为.docx和.xlsx格式的独特zip格式
您的解密函数在文件结尾删除空字节。
good.docx
文件以4个0x00
字节结束,而bad.docx
文件以无结束。 除了那些丢失的字节,这些文件是相同的。
$ wc -c good.docx
25123 good.docx
$ wc -c bad.docx
25119 bad.docx
$ tail -c 32 good.docx | od -x
0000000 6666 6365 7374 782e 6c6d 4b50 0605 0000
0000020 0000 0010 0010 041c 0000 5df1 0000 0000
$ tail -c 32 bad.docx | od -x
0000000 7469 4568 6666 6365 7374 782e 6c6d 4b50
0000020 0605 0000 0000 0010 0010 041c 0000 5df1
如果跳过good.docx
的最后四个字节,那么md5总和恰好匹配:
$ head -c -4 good.docx | md5sum
fbd32fbcc02d62dfd8bd39d390252a4b *-
$ cat bad.docx | md5sum
fbd32fbcc02d62dfd8bd39d390252a4b *-
链接地址: http://www.djcxy.com/p/45451.html