2

現在、次のPHP関数を使用して、ユーザーがファイルを選択してダウンロードできるようにしています。これはFTP経由で発生します。ただし、ユーザーが大きなファイルを選択した場合、ダウンロードの実行中に、他の要求に対してサーバーがロックされます。PHPがリクエストに応答し続けている間にファイルをホストする方法はありますか?

ユーザーが自分の資格情報を使用してファイルをダウンロードすることを許可されていることを確認するためにPHPが必要なので、アセットとしてホストすることはできません。ファイルはFTPサーバーにあります。

function download($file) {
    $fileStream = "";
    if($this->get($file)) {
        //Send header to browser to receive a file
        header("Content-disposition: attachment; filename=\"$file\"");
        header("Content-type: application/octet-stream");
        header("Pragma: ");
        header("Cache-Control: no-cache");
        header("Expires: 0");

        $data = readfile($this->downloadDir . $file);
        $i=0;
        while ($data[$i] != "")
        {
            $fileStream .= $data[$i];
            $i++;
        }
        unlink($this->downloadDir . $file);
        echo $fileStream;
        exit;
    } else {
        return false;
    }
}
4

2 に答える 2

1

PHPはシングルスレッドであるため、リクエストごとに構造を作成する必要があります。次に、一度に1つのリクエストを処理するのではなく、構造をループして、すべてを同時にゆっくりと処理する必要があります(たとえば、数百kbを1つに送信してから、次のリクエストに移動するなど)。

正直なところ、PHPはこの仕事をするのに適切な言語のようには聞こえません。vsftpなどの専用FTPサーバーを使用してみませんか?

于 2013-01-20T22:43:00.957 に答える
1

PHPはこの種の作業に最適なソリューションではありませんが、使用しているWebサーバーにジョブを委任することはできます。また、ファイルはアプリケーションと同じ場所にあるため、これは機能します。

通常PHPアプリケーション( Apachelighttpdnginx )を実行するすべての主要なWebサーバーは、すべてをサポートしていXSendfileます。

これを使用するには、最初にWebサーバーで機能を有効にする必要があり(各Webサーバーについて上記のリンクを確認してください)、次にスクリプトに新しいヘッダーを追加します。

Apache:

header("X-Sendfile: $location_of_file_to_download");

Lighttpd:

header("X-LIGHTTPD-send-file: $location_of_file_to_download");

nginx:

header("X-Accel-Redirect: $location_of_file_to_download");

Webサーバーは、アプリケーションからこのヘッダーをキャッチし、PHP応答の本文をファイルに置き換えます。そして、このファイルをユーザーに提供している間、PHPはブロックが解除され、新しいユーザーを提供する準備が整います。

(他のヘッダーは保持されるため、content-typeヘッダーとcontent-dispositionヘッダーを保持できます)

于 2013-01-20T23:17:06.450 に答える