【PHP】ファイルダウンロード処理を記述する場合の注意点

Agenda
更新日時

 

PHPにおけるファイルダウンロード処理のサンプルを紹介致します。

PHPでファイルダウンロードをする際、ファイルサイズが小さければさほど問題になりませんが、大きなファイルをダウンロードする場合はバッファリングに注意する必要があります。

そうしないとPHPに割り当てられたメモリでは処理できずにファイルダウンロードに失敗します。

 


ファイルダウンロード処理のサンプル


ファイルダウンロード処理のサンプルコードになります。

function download($dir, $file_name, $rename, $mime_type) {
    // ex. dir: /tmp/download/
    // ex. file_name: test.pdf
    $fullpath = $dir . $file_name;

    // ファイルを読み込みできない場合はエラー
    if (!is_readable($file_path)) { die($fullpath); }

    // mimeタイプの指定が無い場合はoctet-streamを設定
    if (empty($mime_type)) {
        $mime_type = "application/octet-stream";
    }

    // ダウンロードファイル名の設定
    if (empty($rename)) {
        $rename = $file_name;
    }

    // Content-Typeにmimeタイプを設定
    header('Content-Type: ' . $mimeType);

    // mimeタイプの自動判定の抑止
    header('X-Content-Type-Options: nosniff');

    // ダウンロードファイルのサイズ
    header('Content-Length: ' . filesize($fullpath));

    // ダウンロード時のファイル名
    header('Content-Disposition: attachment; filename="' . $rename . '"');

    // 出力バッファリングをすべて無効化する
    while (ob_get_level()) { ob_end_clean(); }

    // 出力
    readfile($fullpath);

    exit;
}

ダウンロード対象のファイル名はサーバー上のテンポラリフォルダ内で一意となる文字列を使っていることが多いと思います。

そのため、rename変数にダウンロード時のファイル名を渡すことで、サーバー上のファイル名とは異なるファイル名でダウンロードさせることができます。

readfileの直前にバッファリングを無効化しております。

これがないと大きなサイズのファイルをダウンロードする際に、ファイル内容をすべてバッファに読み込もうとしてしまい、バッファサイズを超えてしまった場合はエラーになってしまいます。

意識していないと忘れがちな部分であり、テスト時に小さなサイズのファイルばかり試していると気づかない部分ですので、異なる言語を扱う際もバッファリングされるかどうかに注意しましょう。

以上です。

カテゴリ

コメントを追加

この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。