我正在为电子商务网站创建受保护的文件下载系统。我使用PHP来验证用户是否已登录并在下载之前拥有该产品。我正在使用PHP.net manual提供的示例,但是在为PDF和PNG文件提供服务时遇到了错误。
在开发期间,它曾在某一点上发挥作用。现在我们已经上线了,它似乎已经破产......幸运的是,该网站目前还没有全力以赴,所以现在这不是一个大问题。
发生了什么:
您访问下载网址。您已被验证为该产品的所有者,并开始下载。一切似乎都很正常,查看标题看起来一切正常。标题声明内容长度为“229542”(224.16kb),看起来没问题。
问题:
下载完成后,文件大小仅为222 字节。没有显示错误,并且文件或浏览器中未发送任何PHP错误/警告/通知。就像PHP被终止一样,但没有任何警告。即使我打开调试,我也看不到任何警告。
源文件looks like this(在Notepad ++中,它是一个PDF,所以它是二进制文件)
下载时,looks like this(仅7行,与2554相比)
我猜:
我相当肯定这个问题与标题有关。也许是由插件引起的?这显示在Chrome的网络控制台中:
响应标题:
以下是响应标头。 “联系:关闭”让我感到担忧。我没有发送那个标题。我猜它是由exit
命令发送的。
Access-Control-Allow-Origin:*
Cache-Control:must-revalidate, post-check=0, pre-check=0
Connection:close
Content-Description:File Transfer
Content-Disposition:attachment; filename="workbook.pdf"
Content-Length:229542
Content-Transfer-Encoding:binary
Content-Type:application/pdf
Date:Tue, 03 Sep 2013 21:16:14 GMT
Expires:0
Pragma:public
Server:Apache
X-Powered-By:PleskLin
我也尝试过:
打开PHP调试以获取某种错误/警告,但我在浏览器或下载的文件源中没有任何有用的东西。
输出到浏览器,而不是流式传输。该文件仍然缩短,我希望PDF会尝试在浏览器的PDF阅读器中显示 - 但它甚至没有尝试。只是一个带有一堆未知符号的白页。
使用+ rb读取模式,使用fopen( $file['file'], 'rb' ); echo fread( $fh, filesize( $file['file'] ) ); fclose( $fh );
使用ignore_user_abort(true)
和set_time_limit(0)
无效(也尝试过set_time_limit(10000),以防万一),
发送.txt
个文件。 这很有用。我尝试使用一个简单的5字节文本文件,再次使用86.3kb文件。两者看起来都和他们进去时一样。所以它必须与二进制文件有关......
/* --- This is what the $file variable looks like:
$file = array(
[file] => /var/www/vhosts/my-website/uploads/workbook.pdf
[type] => application/pdf
[filesize] => 229542
[filename] => workbook.pdf
[upload_date] => 1377278303
);
*/
// Stream the file to the user
if (file_exists($file['file'])) {
header_remove(); // Remove any previously set header
header('Content-Description: File Transfer');
header('Content-Type: ' . $file['type']);
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $filesize);
ob_clean();
flush();
readfile($file['file']);
exit;
}
答案 0 :(得分:1)
我知道这是一个较旧的帖子,但我在这里为每个人提供了解决方案。
您的应用程序中有一个脚本正在压缩空格或其他字符。
ob_start("sanitize_output");
这是我注意到的一个场景中的问题。如果关闭缓冲区缩减脚本(上面称为“sanitize_output”),则.pdf将正常显示。额外的2kb,你注意到被修剪的可能是间距或切掉不需要的字符。
答案 1 :(得分:0)
试试这段代码:只需给$ file一个文件的相对路径并检查它。
<?php
// your file to download
$file = path/to/the/file;
header("Expires: 0");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
$ext = pathinfo($file, PATHINFO_EXTENSION);
$basename = pathinfo($file, PATHINFO_BASENAME);
header("Content-type: application/".$ext);
// tell file size
header('Content-length: '.filesize($file));
// set file name
header("Content-Disposition: attachment; filename=\"$basename\"");
readfile($file);
// Exit script. So that no useless data is output-ed.
exit;
?>
让php计算文件大小和日期等内容。通过阵列输入时可能会发生错误。
同样在这段代码中我使用了pathinfo来自动设置Content-type和文件名。