我目前正在使用以下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;
}
}
答案 0 :(得分:1)
由于PHP是单线程的,因此您必须为每个请求创建一个结构。然后,不是一次只处理一个请求,而是应该遍历结构并同时缓慢地处理所有这些请求(如发送几百kb到一个,然后移到下一个,等等。)
老实说,PHP听起来不是做这项工作的正确语言。为什么不使用像vsftp这样的特制FTP服务器或者那种性质的东西?
答案 1 :(得分:1)
PHP不是此类工作的最佳解决方案,但它可以将作业委派给您正在使用的Web服务器。由于文件与应用程序位于同一位置,因此可以正常工作。
通常运行PHP应用程序(Apache,lighttpd和nginx)的所有主要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就会被解锁并准备好为新用户提供服务。
(其他标题将被保留,因此您可以保留内容类型和内容处置标题)