Загрузка файла HTTP: мониторинг хода загрузки
Я нахожусь в ситуации, когда мне приходится осуществлять загрузку больших файлов (до 4 ГБ) с веб-сервера: Apache 2.4.4 по протоколу HTTP. Я пробовал несколько подходов, но лучшим решением выглядит использование модуля X-SendFile.
Поскольку я предлагаю индикатор выполнения для загрузки файлов, мне потребуется та же функция для загрузки файлов. Итак, вот мои вопросы:
- Есть ли способ, включая обходной путь, для мониторинга хода загрузки файлов?
- Есть ли способ, в том числе обходной путь, для расчета скорости передачи файлов загрузки?
- Есть ли лучший способ обеспечить эффективную загрузку файлов с веб-сервера, чем использование модуля X-Sendfile?
Есть ли вообще лучший вариант загрузки файлов, который позволил бы мне следить за ходом загрузки файлов? Это может быть клиент (JavaScript) или серверное решение (PHP). Есть ли какой-либо конкретный веб-сервер, который позволяет это?
В настоящее время я использую:
- Apache 2.4.4
- Ubuntu
Много раз спасибо.
4 ответа
2 идеи (не проверено):
Первый:
Вместо того, чтобы размещать обычные ссылки на файлы (которые вы хотите загрузить) на своей странице, размещайте ссылки вроде.../dowanload.php, которые могут выглядеть так:
<?php
// download.php file
session_start(); // if needed
$filename = $_GET['filename']);
header( 'Content-type: text/plain' ); // use any MIME you want here
header( 'Content-Disposition: attachment; filename="' . htmlspecialchars($filename) . '"' );
header( 'Pragma: no-cache' );
// of course add some error handling
$filename = 'c:/php/php.ini';
$handle = fopen($filename, 'rb');
// do not use file_get_contents as you've said files are up to 4GB - so read in chunks
while($chunk = fread($handle, 1000)) // chunk size may depend on your filesize
{
echo $chunk;
flush();
// write progress info to the DB, or session variable in order to update progress bar
}
fclose($handle);
?>
Таким образом, вы можете следить за процессом загрузки. Тем временем вы можете записать информацию о прогрессе в DB/ сеанс var и обновить статус чтения индикатора выполнения из DB/ сеанса var, используя AJAX, конечно, опрашивая скрипт, который читает информацию о прогрессе.
Это очень упрощено, но я думаю, что это может работать как вы хотите.
Во-вторых:
Apache 2.4 имеет встроенный язык Lua:
Могу поспорить, что вы можете попытаться написать обработчик LUA Apache, который будет следить за вашей загрузкой - отправлять прогресс в БД и обновлять индикатор выполнения с помощью PHP/AJAX, получая информацию о прогрессе из БД.
Аналогично - существуют модули для Perl и даже Python (но не для Win)
Чтение и запись в базу данных через короткие промежутки времени убивает производительность.
Я бы предложил использовать сеансы (увеличивая значение отправляемых данных в цикле), с которыми вы можете безопасно отключиться с помощью совершенно другого php-файла, вы можете вернуть данные в виде JSON, который может использоваться функцией / плагином javascript.
Я вижу главную проблему в том, что в решении php+apache буферизация вывода может быть размещена в нескольких местах:
Браузер <= 1 => Apache <= 2 => Обработчик PHP <= 3 => Процесс интерпретатора PHP
Вам нужно контролировать первый буфер. Но напрямую из PHP это невозможно.
Возможные решения:
1) Вы можете написать собственный мини-демон, основной функцией которого будет только отправка файлов, и запускать его, например, не на 80 порту 8880. И процесс загрузки файлов и мониторинга выходного буфера оттуда. Ваш выходной буфер будет только один, и вы можете управлять им:
Браузер <= 1 => Процесс интерпретатора PHP
2) Также вы можете взять mod_lua и контролировать выходные буферы напрямую из apache.
3) Также вы можете взять nginx и контролировать выходные буферы nginx, используя встроенный perl (это стабильно)
4) Попробуйте использовать встроенный веб-сервер PHP и напрямую контролировать выходной буфер php. Я не могу ничего сказать о том, как это стабильно, извините. Но вы можете попробовать.;)
Я думаю, что встроенный в Perl nginx+php+ является более стабильным и мощным решением. Но вы можете выбрать и, возможно, использовать другое решение, не указанное в этом списке. Я буду следить за этой темой и с интересом жду вашего окончательного решения.
Если вы используете php версию>= 5.4, это может помочь вам http://www.php.net/manual/en/session.upload-progress.php