我们使用PHP脚本来进行隧道文件下载,因为我们不希望公开可下载文件的绝对路径:
header("Content-Type: $ctype");
header("Content-Length: " . filesize($file));
header("Content-Disposition: attachment; filename=\"$fileName\"");
readfile($file);
Run Code Online (Sandbox Code Playgroud)
不幸的是,我们注意到最终用户无法恢复通过此脚本传递的下载.
有没有办法支持这种基于PHP的解决方案的可恢复下载?
使用PHP,我正在尝试提供大型文件(最多可能为200MB),由于授权问题,这些文件不在Web可访问目录中.目前,我使用一个readfile()调用以及一些标头来提供文件,但似乎PHP在发送之前将其加载到内存中.我打算在共享托管服务器上部署,这将不允许我使用大量内存或添加我自己的Apache模块,如X-Sendfile.
出于安全原因,我不能让我的文件位于Web可访问目录中.有没有人知道我可以在共享托管服务器上部署的内存密集度较低的方法?
编辑:
if(/* My authorization here */) {
$path = "/uploads/";
$name = $row[0]; //This is a MySQL reference with the filename
$fullname = $path . $name; //Create filename
$fd = fopen($fullname, "rb");
if ($fd) {
$fsize = filesize($fullname);
$path_parts = pathinfo($fullname);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf");
break;
case "zip":
header("Content-type: application/zip");
break;
default:
header("Content-type: application/octet-stream");
break;
}
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) …Run Code Online (Sandbox Code Playgroud) 我已经看到很多关于如何有效地使用PHP下载文件而不是允许直接HTTP请求(保持文件安全,跟踪下载等)的问题.
答案几乎总是PHP readfile().
但是,虽然它在使用大文件进行测试时效果很好,但是当它在拥有数百个用户的实时网站上时,下载开始挂起并且PHP内存限制已经耗尽.
那么readfile()当流量高时,导致内存爆炸的工作原理是什么呢?我以为它应该通过直接写入输出缓冲区绕过大量使用PHP内存?
编辑:(澄清一下,我正在寻找"为什么",而不是"我能做什么".我认为Apache的mod_xsend文件是规避的最好方法)
我似乎找不到很多关于X-Sendfile或PHP示例代码的文档(有一些rails代码).
以前有人用过它,会介意快速提供代码片段和简要说明吗?
我正在使用PHP开发电子商务应用程序.为了保证URL的安全,产品下载链接保留在PHP之后.有一个文件,比如download.php,它通过GET接受几个参数并根据数据库验证它们.如果一切顺利,它使用PHP中的readfile()函数提供文件.
现在问题来自传递给readfile()的文件大于php.ini中设置的内存限制因为这个应用程序将被许多用户用于共享托管,我们无法继续改变php.ini设置.
在我们寻找变通方法的努力中,我首先想到我们可以在while循环中进行fread()调用,但似乎会出现问题以及突出显示在PHP中可靠地下载大文件
所以我最好的选择是检测/检查服务器是否支持X-Accel-Redirect(如果是Nginx)/ X-Sendfile(如果是Apache)
如果服务器支持X-Accel-Redirect/X-Sendfile,我可以使用它们,在else块中我可以让系统管理员知道php.ini强制执行的内存限制
理想情况下,我希望尽可能使用像X-Accel-Redirect/X-Sendfile这样的服务器端支持,如果这不起作用 - 我希望有一个回退代码来读取没有readfile()的文件.
我还不确定while循环中的readfile()和fread()是如何不同的,但似乎while循环会产生问题,再次,如在PHP中可靠地下载大文件中所建议的那样
希望得到一些帮助,建议,代码,指导.
谢谢阅读.
我正在尝试向用户提供大型zip文件.当有2个并发连接时,服务器内存不足(RAM).我将内存量从300MB增加到4GB(Dreamhost VPS)然后它工作正常.
我需要允许超过2个并发连接.实际的4GB将允许20个并发连接(太糟糕).
好吧,我正在使用的当前代码需要内存的两倍,然后是实际的文件大小.这太糟糕了.我希望将文件"流式传输"给用户.所以我分配的不仅仅是为用户提供的块.
以下代码是我在CodeIgniter(PHP框架)中使用的代码:
ini_set('memory_limit', '300M'); // it was the maximum amount of memory from my server
set_time_limit(0); // to avoid the connection being terminated by the server when serving bad connection downloads
force_download("download.zip", file_get_contents("../downloads/big_file_80M.zip"));exit;
Run Code Online (Sandbox Code Playgroud)
force_download函数如下(CodeIgniter默认帮助函数):
function force_download($filename = '', $data = '')
{
if ($filename == '' OR $data == '')
{
return FALSE;
}
// Try to determine if the filename includes a file extension.
// We need it in order to set the MIME type
if …Run Code Online (Sandbox Code Playgroud) 我正在使用php下载文件,而不是在新窗口中打开文件本身.它似乎适用于较小的文件,但不适用于大文件(我需要这个工作在非常大的文件).这是我下载文件的代码:
function downloadFile($file) {
if (file_exists($file)) {
//download file
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: '.filesize($file));
ob_clean();
flush();
readfile($file);
exit;
};
};
Run Code Online (Sandbox Code Playgroud)
但是当我尝试下载一个大文件(例如265mb)时,浏览器告诉我它无法找到该文件?这些文件肯定在服务器上,并且脚本适用于较小的文件.有没有办法下载类似于我已有的大文件?
我试图让这个代码工作,但由于某种原因,所有的回声都能够输出正确的内容,但标题似乎不想强制下载我的文档.以下是我试图为文件下载构建的文件.它被设置为输入如下代码:根据用户权限downloader.php?f=13&t=doc下载已命名的文件201-xxx.doc或201-xxx.pdf从两个文件夹中的一个文件夹下载.
所有逻辑都适用于底部的标题信息.如果我注释掉标题内容类型和标题内容处置,那么它会将文件读入浏览器.如果包含这些行中的任何一行,它会给出一个错误"Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found."
<?php
//ob_start();
if ( !defined('__DIR__') ) define('__DIR__', dirname(__FILE__));
define( "TLOJ_FSROOT", __DIR__ . "/" );
define('WP_USE_THEMES', false);
require('./wp-blog-header.php');
$lessonnumber = $_REQUEST['f'];
$type = $_REQUEST['t'];
if ( $lessonnumber < '10' ) { $threedigitlesson = '00' . $lessonnumber; }
elseif ( $lessonnumber < '100' ) { $threedigitlesson = '0' . $lessonnumber; }
else { $threedigitlesson = $lessonnumber; }
$filenamestart = "201-" . $threedigitlesson;
$contenttype …Run Code Online (Sandbox Code Playgroud) 可能重复:
在PHP中可靠地发送大文件
我将分发一个PHP脚本,使人们可以通过掩码URL从服务器向他们的客户提供可下载的产品(不想泄露服务器上的位置).有些文件可能非常大,所以我需要确保使用能够处理更大文件的方法.
我熟悉如何利用以下每种下载方法,我只想问哪个是最好的(最有效,最可靠,普遍支持等):
流fopen
流式cURL
的file_get_contents
卷曲
php ×9
download ×5
apache ×3
memory ×3
large-files ×2
readfile ×2
codeigniter ×1
curl ×1
fopen ×1
nginx ×1
x-sendfile ×1