更新日時
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($fullpath)) { 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の直前にバッファリングを無効化しております。
これがないと大きなサイズのファイルをダウンロードする際に、ファイル内容をすべてバッファに読み込もうとしてしまい、バッファサイズを超えてしまった場合はエラーになってしまいます。
公式のマニュアルにも注意書きされているので詳細はこちらをご参照ください。
意識していないと忘れがちな部分であり、テスト時に小さなサイズのファイルばかり試していると気づかない部分ですので、異なる言語を扱う際もバッファリングされるかどうかに注意しましょう。
以上です。
コメント
コメントを追加
あわせて読みたい記事はこちら
- 関連記事はありません。
if (!is_readable($file_path)) { die($fullpath); }
は
if (!is_readable($fullpath)) { die($fullpath); }
の間違いですかね。