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, но это решение вынудило бы меня запретить частичную загрузку для большинства, так как у меня были проблемы с подсчетом используемой пропускной способности.
1 answers
Я вижу два немедленных решения вашей проблемы:
- Найдите другого хоста, который не занимается подобными вещами
- Вместо того, чтобы позволить скрипту управлять загрузкой, позвольте apache сделать это, просто перенаправьте на фактический файл после обновления ваших счетчиков и тому подобного.
header('Location: '.$actualFile, true, 303)
(303 означает "Просмотреть другой ресурс", чтобы предотвратить повторную публикацию данных по следующему URL-адресу) После этого вы можете простоexit;