使用download.php下载文件 [英] Downloading files with download.php

查看:62
本文介绍了使用download.php下载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要向客户交付大文件,如 file.zip (约2 GB),并为每个客户提供唯一的URL.然后,我将(使用 .htaccess 重定向)客户下载链接 example.com/download/f6zDaq/file.zip 到类似的内容

I need to deliver big files like file.zip (~2 GB) to customers, with a unique URL for each customer. Then I will redirect (with .htaccess) a customer download link example.com/download/f6zDaq/file.zip to something like

example.com/download.php?id=f6zDaq&file=file.zip

但是,由于文件很大,因此我不希望PHP处理下载(而不只是让Apache处理下载)成为我服务器的CPU/RAM性能问题.毕竟,要求PHP执行此操作涉及一个新层,因此,如果执行不正确,它可能会引起此类问题.

But as the files are big, I don't want the fact that PHP processes the downloading (instead of just letting Apache handle it) to be a CPU / RAM performance issue for my server. After all, asking PHP to do it involves a new layer, so it might cause such an issue, if not done properly.

问题:在以下解决方案中,哪种是最佳实践?(尤其是在CPU/RAM方面)?

Question: among the following solutions, which one(s) are the best practice? (in particular, in terms of CPU/RAM)?

  • 1:具有 application/download

header('Content-Type: application/download');
header('Content-Disposition: attachment; filename=file.zip');
readfile("/path/to/file.zip");

下载时测得的CPU使用率:13.6%.

CPU usage measured while downloading: 13.6%.

1bis:具有 application/octet-stream 的PHP解决方案(来自

1bis: PHP solution with application/octet-stream (coming from Example #1 of this page)

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=file.zip');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('file.zip'));
readfile("/path/to/file.zip");

  • 1之三:具有 application/octet-stream 的PHP解决方案(来自此处):

  • 1ter: PHP solution with application/octet-stream (coming from here):

    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename=file.zip'); 
    header('Content-Transfer-Encoding: binary'); // additional line
    header('Connection: Keep-Alive');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); // additional line
    header('Pragma: public');
    header('Content-Length: ' . filesize('file.zip'));
    readfile("/path/to/file.zip");
    

  • 1之四:另一个具有 application/force-download 的PHP变体(已编辑;来自此处):

  • 1quater: Another PHP variant with application/force-download (edited; coming from here):

    header("Content-Disposition: attachment; filename=file.zip");
    header("Content-Type: application/force-download");
    header("Content-Length: " . filesize($file));
    header("Connection: close");
    

  • 2:Apache解决方案,不涉及PHP:让Apache提供文件,并使用 .htaccess 为同一文件提供不同的URL(可以用多种方式编写).在性能方面,这类似于让客户下载由Apache服务器提供的 example.com/file.zip .

  • 2: Apache solution, no PHP involved: let Apache serve the file, and use .htaccess to provide different URL for the same file (many ways to do it can be written). In terms of performance, it's similar to let the customer download example.com/file.zip, served by Apache server.

    3:另一个PHP解决方案.这可能会起作用:

    3: Another PHP solution. This would probably work:

    $myfile = file_get_contents("file.zip");
    echo $myfile;
    

    但是这不会要求PHP将全部内容加载到内存中吗?(就性能而言,这是很糟糕的!)

    but wouldn't this ask PHP to load the whole content in memory? (which would be bad in terms of performance!)

    4:只需执行 header("Location:/abcd/file.zip"); 重定向,如

    4: Just do a header("Location: /abcd/file.zip"); redirection as explained in File with a short URL downloaded with original filename.

    此解决方案的问题:这会公开文件的实际位置

    Problem with this solution: this discloses the actual location of the file

     example.com/abcd/file.zip
    

    不需要的最终用户(然后该用户无需身份验证即可使用或共享此URL)...

    to the end user (who can then use or share this URL without authentification) which is not wanted...

    但是,另一方面,由于PHP只是重定向请求,而不是传递文件本身,因此对CPU来说要轻得多.

    But on the other hand, it is much lighter for the CPU since PHP just redirects the request and doesn't deliver the file itself.

    下载时测得的CPU使用率:10.6%.

    CPU usage measured while downloading: 10.6%.

    注意: readfile 文档说:

    Note: the readfile doc says:

    readfile()本身不会出现任何内存问题,即使在发送大文件时也是如此.如果遇到内存不足错误,请确保使用ob_get_level()关闭输出缓冲.

    readfile() will not present any memory issues, even when sending large files, on its own. If you encounter an out of memory error ensure that output buffering is off with ob_get_level().

    但是我想100%确保它不会比纯Apache解决方案慢/更多的CPU/RAM饥饿.

    推荐答案

    然后我将其添加到 apache2.conf 中:

    <Directory />
      AllowOverride All
      Require all granted
      XSendFile on
      XSendFilePath /home/www/example.com/files/
    </Directory>
    

    然后,我重新启动了 service apache2 ,并将其包含在 .htaccess 中:

    I then did service apache2 restart and included this in .htaccess:

    RewriteRule ^(.*)$ download.php?file=$1 [L,QSA]
    

    ,这在 download.php 中:

    header("X-Sendfile: /home/www/example.com/files/hiddenfolder_w33vbr0upk80/" . $file);
    header("Content-type: application/octet-stream");
    header('Content-Disposition: attachment; filename="' . $file . '"');
    

    NB:奇怪的是,即使我在 apache2.conf VirtualHost中启用了 AllowOverride All ,也是这样做的:

    NB: strangely, even I have AllowOverride All enabled in the apache2.conf VirtualHost, doing this:

    XSendFile on
    XSendFilePath /home/www/example.com/files/
    

    仅在/home/www/example.com/.htaccess /home/www/example.com/files/.htaccess 文件中(由于 xsendFilePath不允许,此处失败).

    just in the /home/www/example.com/.htaccess or /home/www/example.com/files/.htaccess file didn't work (it fails with xsendFilePath not allowed here).

    基准:

    • 下载时为10.6%的CPU,就像我直接用Apache直接下载文件(完全没有PHP)一样,所以一切都很好!

    这篇关于使用download.php下载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆