PHP readfile не работает, но только для 20+ мегабайт файлов - PullRequest
0 голосов
/ 27 февраля 2012

Небольшой скрипт, используемый для отправки пользователю одного из двух файлов .pdf на основе строки get:

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 ();перед файлом чтения и добавлением заголовка ('Content-Length:'. filesize ('d /'. $ filename));- это работает успешно, но на обработку уходит около 2 минут (т. е. как только я нажимаю на URL, в течение 2 минут ничего не происходит, а затем появляется диалоговое окно с актуальным файлом для загрузки в нем правильно).

Любая помощь будет высоко ценится.Jon

Ответы [ 3 ]

2 голосов
/ 27 февраля 2012

Да, ваша проблема, скорее всего, заключается в тайм-ауте 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;
    }
 }
?>
0 голосов
/ 27 февраля 2012

При потоковой передаче файла убедитесь, что у вас отключена буферизация вывода. В противном случае PHP с буфером весь файл. В вашем случае PHP, вероятно, не хватает памяти, потому что он буферизирует весь файл. Добавьте ob_clean, очистите перед файлом чтения:

ob_clean();
flush();
readfile('d/' . $filename);

Браузер не будет иметь тайм-аут, пока он получает данные, поэтому загрузка может занять 10 минут, если это необходимо.

0 голосов
/ 27 февраля 2012

Может ли быть так, что загрузка занимает слишком много времени и достигает тайм-аута вашего PHP-скрипта?

Более чистым решением будет перенаправление на правильный файл, если это возможно, и позволить веб-серверу обрабатывать его напрямую.

<?php header('Location: http://www.example.com/d/' . $filename) ;?>
...