6

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

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 文件(标题部分)

$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 调用的,如下所示:

download.php?id=a2a9ca5bd4a84294b421fdd9ef5e438ded7fcb09

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

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

4

2 回答 2

13

好的 - 这里有几个问题:

1)根据 nginx 开发人员的说法,将root 放在一个位置内是一个坏主意。

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

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

您的项目应布置为:

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

您的 Nginx 配置文件应如下所示:

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 获取内部位置:

$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);
于 2013-04-24T15:51:05.170 回答
3

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

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

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

我是 nginx 的新手,因为从 Apache 切换似乎真的更快。谢谢大佬不吝赐教!我很高兴成为 Stackoverflow 社区的一员 :)

于 2013-04-25T09:07:46.643 回答