Загрузка файла 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

Другие вопросы по тегам