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開発者によると、ルートを場所の中に置くことは悪い考えです。

2) これが内部リダイレクトであることを Nginx に伝えるために使用される内部 URL は、ユーザーに公開されるべきではありません。

3) あなたの download.php ファイルがどこから提供されているかわかりません。そのため、/download.php へのリクエストが index.php ではなくそのファイルによって提供されるように、try_files を使用するようにルート ロケーション ブロックを変更しました。

プロジェクトは次のようにレイアウトする必要があります。

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 ヘッダーからの要求に一致できるようにする単なる文字列です。

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 Server では、次のようにエイリアスにフル パスを設定する必要があることがわかりました。

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

追加のスラッシュが必要であることに注意してください (私の場合、開発では Windows 7 Pro、展開では Windows Server 2008 です)。唯一の問題は、同時ダウンロードをテストして、サーバー リソースが大量に消費されているかどうかを確認する必要があることです。

Apacheから切り替える方が本当に速いように見えるので、nginxは初めてです。啓発してくれてありがとう!Stackoverflow コミュニティに参加できてうれしいです :)

于 2013-04-25T09:07:46.643 に答える