PHP读取文件没有';不起作用,但仅适用于20多个meg文件


PHP readfile doesn't work, but only for 20+ meg files

小脚本,用于根据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分钟。