使用 PHP 和 nginx X-Accel-Redirect 提供大文件 [英] Serve large file with PHP and nginx X-Accel-Redirect

查看:28
本文介绍了使用 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: applicationpdf');
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 放入一个位置是一个坏主意.

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 配置应该是这样的:

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: applicationpdf');
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天全站免登陆