5

我处于一种情况,当我必须从 Web 服务器下载大文件(最大 4GB)时:通过 HTTP 协议的 Apache 2.4.4。我尝试了几种方法,但最好的解决方案似乎是使用 X-SendFile 模块。

当我为文件上传提供进度条时,我需要为文件下载提供相同的功能。所以这是我的问题:

  • 有什么方法,包括变通方法,来实现文件下载进度监控?
  • 有什么方法(包括解决方法)来计算文件下载传输速度?
  • 有没有比使用 X-Sendfile 模块更好的方法从 Web 服务器提供有效的文件下载?

一般有没有更好的文件下载选项,可以让我监控文件下载进度?它可以是客户端 (JavaScript) 或服务器解决方案 (PHP)。是否有任何特定的网络服务器允许这样做?

目前我使用:

  • 阿帕奇 2.4.4
  • Ubuntu

多次感谢。

4

3 回答 3

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);
?>

这样您就可以密切关注您的下载过程。同时,您可以使用 AJAX 将进度信息写入 DB/session var 并从 DB/session var 更新进度条读取状态,当然还要轮询读取进度信息的脚本。

这非常简化,但我认为它可能会按您的意愿工作。

第二:

Apache 2.4 内置了 Lua 语言:

我敢打赌,您可以尝试编写 LUA Apache 处理程序来监控您的下载 - 将进度发送到数据库并使用 PHP/AJAX 从数据库获取进度信息来更新进度条。

同样 - 有 perl 甚至 python 的模块(但不是 win)

于 2013-10-28T17:24:22.937 回答
2

我看到的主要问题是:在 php+apache 解决方案中,输出缓冲可能放置在几个地方:

浏览器 <= 1 => Apache <= 2 => PHP 处理程序 <= 3 => PHP 解释器进程

您需要控制第一个缓冲区。但是直接从 PHP 是不可能的。

可能的解决方案:

1)您可以编写自己的迷你守护程序,其主要功能将仅发送文件并在例如 80 端口 8880 以外的其他端口上运行。并从那里处理下载文件并监视输出缓冲区。您的输出缓冲区将只有一个,您可以控制它:

浏览器 <= 1 => PHP 解释器进程

2) 你也可以直接从 apache 获取 mod_lua 和控制输出缓冲区。

3)您也可以使用内置的 perl获取nginx并控制 nginx 输出缓冲区(它是稳定的)

4) 尝试使用PHP 内置的 web 服务器并直接控制 php 输出缓冲区。我不能说它是如何稳定的,抱歉。但是你可以试试。;)

我认为 nginx+php+内置 perl 是更稳定和强大的解决方案。但是您可以选择并且可能使用该列表中没有的其他解决方案。我将关注这个主题并感兴趣地等待您的最终解决方案。

于 2013-10-29T06:20:37.500 回答
2

以较短的间隔读取和写入数据库会降低性能。

我建议使用会话(增加循环中发送数据的值),您可以通过另一个 php 文件安全地关闭它,您可以将数据作为 JSON 返回,可供 javascript 函数/插件使用。

于 2013-10-30T12:49:02.300 回答