使用PHP和Nginx X-Accel-Redirect服务大型文件 [英] Serve large file with PHP and nginx X-Accel-Redirect

查看:82
本文介绍了使用PHP和Nginx X-Accel-Redirect服务大型文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望用户能够从配置了nginx PHP的服务器(Windows)中下载PDF文件.这是我的nginx.conf(服务器块)

Hi I want user to be able to download PDF file from my server (Windows) configured with nginx PHP. This is my nginx.conf (server block)

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.php;

        }

         location /download {
            internal;
            alias /protected;
        }
    }
}

..和PHP文件(标题部分)

..and the PHP file (header part)

$file = '/download/real-pdf-file.pdf'; //this is the physical file path
$filename = 'user-pdf-file.pdf'; //this is the file name user will get
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: application\pdf');
header('Content-Length: ' .(string)(filesize($file)) );
header('Content-Disposition: attachment; filename='.$filename.'');
header('Content-Transfer-Encoding: binary');
header('X-Accel-Redirect: '. $file);

文件是通过URL调用的,如下所示:

The file is call from URL like this:

download.php?id=a2a9ca5bd4a84294b421fdd9ef5e438ded7fcb09

我从这里尝试过很少的示例/解决方案,但到目前为止,没有一个有效.该文件很大(每个文件介于250到400 MB之间),每个用户都可以下载4个文件.

I've try few example/solution from here but so far none is working. The file is large (between 250 to 400 MB each) and each user will be able to download 4 files.

使用PHP下载部分没有问题,只有似乎无法正常工作的nginx配置.没有检测到错误日志.

There is no issue with downloading part using PHP, only the nginx configuration that seem not working. No error log detected.

推荐答案

好的-这里有几个问题:

Ok - there's a couple of issues here:

1)根据nginx开发人员的说法,将root放置在某个位置是 Bad IDEA .

1) Puting root inside of a location is a BAD IDEA according to the nginx developers.

2)不应向用户公开用于告诉Nginx这是内部重定向的内部URL.

2) The internal URL used for telling Nginx that this is an internal redirect shouldn't be exposed to users.

3)我看不到从哪里提供您的download.php文件,因此我将您的根目录块更改为使用try_files,因此对/download.php的请求将由该文件而不是index.php提供

3) I can't see where your download.php file is being served from, so I changed your root location block to use try_files so a request to /download.php would be served by that file rather than index.php.

您的项目的布局应为:

project\
    html - this is the root of your website
    protected  - this directory is not accessible directly

您的Nginx conf看起来应该像这样:

And your Nginx conf should look like:

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;

        root   /path/to/project/html;

        location / {
            try_files $uri /index.php?$args;
        }

        location /protected_files {
            internal;
            alias /path/to/project/protected;
        }
    }
}

一个好主意是不要混淆使用相同的名称来表示不同的含义.我已经更改了它们,以便现在protected仅指代包含要提供的文件的实际物理目录. protected_files只是一个字符串,它允许Nginx匹配来自x-accel标头的请求.

It's a good idea not to re-use the same names to mean different things as it's quite confusing. I've changed them so that now protected just refers to the actual physical directory that holds the files you want to serve. protected_files is just a string that allows Nginx to match the request from the x-accel header.

PHP代码中唯一需要更改的就是使用正确的字符串,以允许Nginx提取内部位置:

The only thing that needs changing in your PHP code is to use the correct string to allow Nginx to pickup the internal location:

$aliasedFile = '/download/real-pdf-file.pdf'; //this is the nginx alias of the file path
$realFile = '/path/to/project/protected/real-pdf-file.pdf'; //this is the physical file path
$filename = 'user-pdf-file.pdf'; //this is the file name user will get
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: application\pdf');
header('Content-Length: ' .(string)(filesize($realFile)) );
header('Content-Disposition: attachment; filename='.$filename.'');
header('Content-Transfer-Encoding: binary');
header('X-Accel-Redirect: '. $aliasedFile);
exit(0);

这篇关于使用PHP和Nginx X-Accel-Redirect服务大型文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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