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

Agenda
更新日時
article_92_eye_catch

 

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の直前にバッファリングを無効化しております。

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

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

以上です。

カテゴリ

コメントを追加

This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.

画像CAPTCHA
画像内に表示されている文字列を入力してください。