小脚本,用于根据get字符串向用户发送两个.pdf文件中的一个:
if ($fileToSend == "bigone") {
$filename = "largefile.pdf";
$header = "application/pdf";
} else if ($fileToSend == "smallone") {
$filename = "smallfile.pdf";
$header = "application/pdf";
}
if (file_exists('d/' . $filename)){
header('Content-type: ' . $header);
header('Content-disposition: attachment; filename=' . $filename);
readfile('d/' . $filename);
} else {
echo('No good');
}
文件d/smallfile.pdf和d/largefile.pdf都存在。smallfile.pdf大约5毫克。largefile.pdf大约25毫克。
sendFile.php?fileToSend=smallone有效。
sendFile.php?fileToSend=bigone不起作用;在FF,它说
找不到文件Firefox在[url]/sendFile.php中找不到该文件?fileToSend=bigone
没有文件名错误。
我试过
- 添加flush();在读取文件之前;这会导致出现下载文件对话框,但随后会提供一个0字节的文件
- 添加flush();在readfile之前,并添加标头('Content-Length:'.filesize('d/'.$filename));-这很成功,但需要近2分钟的时间来处理(即,一旦我点击URL,在近2分钟内什么都没有发生,然后出现对话框,其中包含要正确下载的实际文件)
任何帮助都将不胜感激。Jon
是的,你的问题很可能是php在给你提供文件时超时,对此的补救措施是给你提供块,这样就不会咀嚼内存和set_time_limit(0);
,这样它就不会在60秒后超时:
<?php
if(isset($_GET['fileToSend'])){
switch($_GET['fileToSend']){
case "bigone":
if(downloadFile("./d/largefile.pdf")===false){
//failed, do somthing
}
break;
case "smallone":
if(downloadFile("./d/smallfile.pdf")===false){
//failed, do something
}
break;
default:
echo 'No file selected';
break;
}
}
function downloadFile($file){
if (file_exists($file)) {
if(is_dir($file)){return false;}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file)).'"';
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
$handle = fopen($file, "rb");
$chunksize=(filesize($file)/1024);
set_time_limit(0);
while (!feof($handle)) {
echo fgets($handle, $chunksize);
flush();
}
fclose($handle);
die;
}else{
return false;
}
}
?>
可能是下载花费了太多时间并达到了PHP脚本的超时时间吗?
如果可能的话,一个更干净的解决方案是重定向到正确的文件,并让web服务器直接处理它。
<?php header('Location: http://www.example.com/d/' . $filename) ;?>
流式传输文件时,请确保禁用了输出缓冲。否则PHP会缓冲整个文件。在您的情况下,PHP可能内存不足,因为它正在缓冲整个文件。添加ob_clean,在读取文件之前刷新:
ob_clean();
flush();
readfile('d/' . $filename);
只要浏览器正在接收数据,它就不会超时,因此如果需要,下载可能需要10分钟。