PHP如何正确托管大文件?

时间:2013-01-20 22:35:16

标签: php html ftp timeout request

我目前正在使用以下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;
    }
}

2 个答案:

答案 0 :(得分:1)

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

老实说,PHP听起来不是做这项工作的正确语言。为什么不使用像vsftp这样的特制FTP服务器或者那种性质的东西?

答案 1 :(得分:1)

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

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

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

的Apache:

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

Lighttpd的:

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

nginx的:

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

Web服务器将从您的应用程序中捕获此标头,并将使用该文件替换PHP响应的主体。当它将这个文件提供给用户时,PHP就会被解锁并准备好为新用户提供服务。

(其他标题将被保留,因此您可以保留内容类型和内容处置标题)