php - 使用 PHP 和 nginx X-Accel-Redirect 服务大文件

标签 php nginx

您好,我希望用户能够从我配置了 nginx PHP 的服务器 (Windows) 下载 PDF 文件。这是我的 nginx.conf(服务器 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 文件(头部分)

$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配置好像不行。未检测到错误日志。

最佳答案

好的 - 这里有几个问题:

1) 将 root 放在一个位置内是一个 BAD IDEA根据 nginx 开发人员的说法。

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

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

您的项目应布局为:

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

你的 Nginx conf 应该是这样的:

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 header 的请求。

唯一需要在您的 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);

关于php - 使用 PHP 和 nginx X-Accel-Redirect 服务大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16189758/

相关文章:

php - 如何找到最接近的匹配数组

php - 如何在mysql中获取当前登录的用户?

ubuntu - 为 Ominbus 安装程序的 GitLab 社区版启用 HTTPS 自签名证书

带 PHP5-FPM 的 Nginx——.php 文件显示空白屏幕

ubuntu - Certbot 错误配置错误 : nginx restart failed

php - 如何通过循环将php数组中对象的值写入mysql

php - 通过 curl 和 mcrypt 连接两台服务器

php - 如何从存储库中获取鉴别器类型

python - 以模块化方式组织 Pyramid/粘贴器配置文件

docker - 使用 nginx 在 docker 中托管时缺少 Blazor WASM 样式