2

我目前正在使用以下 PHP 函数来允许用户选择一个文件然后下载它。这发生在 FTP 上。但是,如果用户选择了一个大文件,那么在下载过程中它会锁定服务器以接收任何其他请求。有什么方法可以在让 PHP 继续响应请求的同时托管文件?

我需要 PHP 来验证是否允许用户使用他们的凭据下载文件,因此我不能将其作为资产托管。该文件位于 FTP 服务器上。

function download($file) {
    $fileStream = "";
    if($this->get($file)) {
        //Send header to browser to receive a file
        header("Content-disposition: attachment; filename=\"$file\"");
        header("Content-type: application/octet-stream");
        header("Pragma: ");
        header("Cache-Control: no-cache");
        header("Expires: 0");

        $data = readfile($this->downloadDir . $file);
        $i=0;
        while ($data[$i] != "")
        {
            $fileStream .= $data[$i];
            $i++;
        }
        unlink($this->downloadDir . $file);
        echo $fileStream;
        exit;
    } else {
        return false;
    }
}
4

2 回答 2

1

由于 PHP 是单线程的,因此您必须为每个请求创建一个结构。然后,不是一次只处理一个请求,您应该遍历结构并缓慢地同时处理所有请求(例如将几百 kb 发送到一个请求,然后转到下一个请求,等等)。

老实说,PHP 听起来并不适合做这项工作。为什么不使用专门构建的 FTP 服务器,例如 vsftp 或类似的东西?

于 2013-01-20T22:43:00.957 回答
1

PHP 不是此类工作的最佳解决方案,但它可以将工作委托给您正在使用的 Web 服务器。由于该文件与您的应用程序位于同一位置,因此可以正常工作。

通常运行 PHP 应用程序( Apachelighttpdnginx )的所有主要 Web 服务器都支持XSendfile.

要使用它,您必须首先在您的网络服务器中启用该功能(检查上面每个网络服务器的链接),然后在您的脚本中添加一个新标头:

阿帕奇:

header("X-Sendfile: $location_of_file_to_download");

轻量级:

header("X-LIGHTTPD-send-file: $location_of_file_to_download");

nginx:

header("X-Accel-Redirect: $location_of_file_to_download");

Web 服务器将从您的应用程序中捕获此标头,并将您的 PHP 响应的正文替换为该文件。当它将此文件提供给用户时,PHP 会畅通无阻并准备好为新用户提供服务。

(将保留其他标头,因此您可以保留 content-type 和 content-disposition 标头)

于 2013-01-20T23:17:06.450 回答