web-dev-qa-db-ja.com

php、ファイルのダウンロード

私は簡単なファイルダウンロードスクリプトを使用しています:

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

それは私のローカルサーバーで200mbまで動作しています。

私のウェブサイトでこのコードを試すと、200MBのファイルではなく173KBのファイルがダウンロードされます。

私はすべてをチェックし、いくつかのカスタムコードを作成しました(readfileの代わりにob関数とfreadを使用)が、大きなファイルをダウンロードできません。

ご回答ありがとうございます。

  • 私はApache2.2を使用しています、PHP 5.3
  • すべてのPHP大きなファイルを処理するための設定は問題ありません。(実行時間、メモリ制限、...
16
jsonx

次のコードで私が抱えている問題の1つは、出力ストリームを制御できないことです。バックグラウンドで何が起こっているのかを正確に知らなくても、PHPで処理できます。

あなたがすべきことは、あなたが制御し、複製されたアクロスサーバーができる出力システムをセットアップすることです。

例えば:

if (file_exists($file))
{
    if (FALSE!== ($handler = fopen($file, 'r')))
    {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: chunked'); //changed to chunked
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        //header('Content-Length: ' . filesize($file)); //Remove

        //Send the content in chunks
        while(false !== ($chunk = fread($handler,4096)))
        {
            echo $chunk;
        }
    }
    exit;
}
echo "<h1>Content error</h1><p>The file does not exist!</p>";

これは基本的なことですが、試してみてください。

ここで私の返信も読んでください: file_get_contents => PHP致命的なエラー:許可されたメモリが使い果たされました

19
RobertPitt

Readfileは長いファイルで問題が発生する可能性があるようです。 @Khezが尋ねたように、スクリプトの実行時間が長すぎる可能性があります。すばやくグーグルすると、ファイルをチャンク化する例がいくつかありました。

http://teddy.fr/blog/how-serve-big-files-through-phphttp://www.php.net/manual/en/function.readfile。 php#99406

3
Paul DelRe

特定のシナリオに対する1つの解決策は、PHPスクリプトを使用して、ダウンロードするファイルをインテリジェントに決定できることですが、ファイルをPHPから直接送信する代わりに、クライアントにリダイレクトを返すことができます。このリダイレクトには、処理される直接リンクが含まれます。 Webサーバーだけで。

これは、少なくとも2つの方法で実行できます。たとえば、PHPスクリプトがファイルを「ダウンロードゾーン」にコピーし、他のバックグラウンド/サービススクリプトによって「古い」ファイルから定期的に削除するか、実際の永続的な場所をに公開します。クライアント。

もちろん、各ソリューションの場合と同様に、欠点もあります。これは、ファイルを要求しているクライアント(curl、wget、GUIブラウザー)によっては、ユーザーが作成したリダイレクトをサポートしていない場合があり、もう1つでは、ファイルは外界に非常に公開されており、いつでも読み取ることができます。 PHPスクリプトの(アクセス)制御。

3
Polarlight

本当の解決策は、ファイルをクライアントに送信するためだけにPHPスクリプトを使用することを避けることです。それはやり過ぎであり、Webサーバーはこのタスクにより適しています。

おそらく、PHPを介してファイルを送信する理由があります。おそらく、ユーザーは最初に認証する必要がありますか?その場合は、 X-Accel-Redirect (nginxを使用している場合)または X-Sendfile (以前はX-LIGHTTPD-send-file)を使用する必要があります。 lighttpdで。

Apacheを使用している場合、 mod_xsendfile への参照がいくつか見つかりましたが、個人的に使用したことはなく、ホスティングを管理している場合はインストールされているとは思えません。

これらの解決策が受け入れられない場合は、お詫び申し上げますが、実際の問題に関する詳細情報が本当に必要です。そもそも、なぜこれらのファイルをPHPから送信するのですか?

0
ZoFreX

スクリプト 長く実行できる 十分で、十分なメモリがあることを確認しましたか?

本当に出力バッファリングが必要ですか?

0
Khez