fpassthru на PHP


На моем веб-хостинге есть "убийца процессов", который завершает любой процесс, выполняющийся дольше примерно 5 минут, поэтому мой скрипт загрузки не может работать так долго.

Я подумал, что буду использовать fread-печать в течение нескольких секунд, просто чтобы поймать, если пользователь сначала прервет загрузку, а затем использует fpassthru для сброса остальной части файла.

ob_end_clean();
$file = fopen($this->m_path,'rb'); // read binary
fseek($file, $startByte);
$cnt = 0;
while (!feof($file) && (!connection_aborted()) && ($bytesSent<$bytesToSend) )
{
    $cnt++;
    if($cnt > 25) // to simulate breaking the loop after a certain time has passed
        break;
    set_time_limit(0);
    $buffer = fread($file, 32*1024);
    print($buffer);
    //flush();
    $bytesSent += strlen($buffer);
}
flush(); // has no effect on fpassthru

// --- insert point for the code below --

if(!feof($file))
{
    fpassthru($file);
}
fclose($file);

Проблема в том, что fpassthru поддерживает выполнение скрипта во время всей загрузки. Я устал использовать буферизацию вывода, что приводит к сценарию выход происходит быстро, но загрузка прерывается примерно через 8 минут (я отправляю файл размером 30 МБ со скоростью 15 Кб/с).

Одна вещь, которая позволяет быстро завершить работу скрипта и завершить загрузку, - это если я вставлю следующее в "точку вставки" выше:

echo("X"); // or pretty much any string literal
flush();

Это работает каждый раз, но файл, конечно, повреждается (как и ожидалось).

Если я вместо этого вставлю что-то вроде этого:

echo fread($file, 16);
flush();

Это не работает (fpassthru не позволяет сценарию завершать работу).

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

Версия PHP 5.2.11 Apache 2.2.9

РЕДАКТИРОВАТЬ:

В итоге я заставил своего веб-хостера продлить время ожидания до 40 минут, чтобы я мог обслуживать файлы с помощью fread-echo и выходить чисто с запасом времени. Я обслуживаю относительно небольшие файлы, и возобновление поддерживается для немногих посетители, которым прерывают переводы.

Я также сделал (и отклонил) решение на основе перенаправления, в котором я установил нужные заголовки в .htaccess, но это решение вынудило бы меня запретить частичную загрузку для большинства, так как у меня были проблемы с подсчетом используемой пропускной способности.

Author: hakre, 2010-02-28

1 answers

Я вижу два немедленных решения вашей проблемы:

  1. Найдите другого хоста, который не занимается подобными вещами
  2. Вместо того, чтобы позволить скрипту управлять загрузкой, позвольте apache сделать это, просто перенаправьте на фактический файл после обновления ваших счетчиков и тому подобного. header('Location: '.$actualFile, true, 303) (303 означает "Просмотреть другой ресурс", чтобы предотвратить повторную публикацию данных по следующему URL-адресу) После этого вы можете просто exit;
 2
Author: Kris, 2010-02-28 16:11:22