首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用PHP和nginx X-Accel-Redirect处理大文件

使用PHP和nginx X-Accel-Redirect处理大文件
EN

Stack Overflow用户
提问于 2013-04-24 18:35:04
回答 2查看 16.2K关注 0票数 6

嗨,我想让用户能够从我的服务器(Windows)与nginx PHP配置下载PDF文件。这是我的nginx.conf (服务器块)

代码语言:javascript
复制
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;
        }
    }
}

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

代码语言:javascript
复制
$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调用,如下所示:

代码语言:javascript
复制
download.php?id=a2a9ca5bd4a84294b421fdd9ef5e438ded7fcb09

我在这里尝试了几个示例/解决方案,但到目前为止还没有一个有效。该文件很大(每个文件大小在250到400 MB之间),每个用户可以下载4个文件。

使用PHP下载部分没有问题,只有nginx配置似乎不起作用。未检测到错误日志。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-24 23:51:05

好的-这里有几个问题:

1)根据nginx开发者的说法,将root放在位置内部是一个BAD IDEA

2)用于告知Nginx这是内部重定向的内部URL不能暴露给用户。

3)我看不到您的download.php文件是从哪里提供的,所以我将根位置块更改为使用try_files,以便对/download.php的请求将由该文件而不是index.php提供服务。

你的项目应该是这样的:

代码语言:javascript
复制
project\
    html - this is the root of your website
    protected  - this directory is not accessible directly

并且您的Nginx conf应该如下所示:

代码语言:javascript
复制
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头的请求。

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

代码语言:javascript
复制
$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);
票数 12
EN

Stack Overflow用户

发布于 2013-04-25 17:07:47

根据Danack的建议和解决方案以及Carsten的一些澄清,我发现在Windows服务中,我们需要在别名中设置完整路径,如下所示:

代码语言:javascript
复制
location /protected_files {
            internal;
            alias C:/absolute/path/to/project/protected/;
        }

请注意,需要额外的正斜杠(在我的例子中,Windows 7专业版用于开发,Windows Server 2008用于部署)。唯一的问题是,我现在需要测试并发下载,以查看服务器资源是否被占用。

我是nginx的新手,因为从Apache切换到nginx似乎真的更快。感谢盖伊的启蒙!我很高兴成为Stackoverflow社区的一员:)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16189758

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档