PHPで簡単にPDFが作成できる「mPDF」では、作成したPDFをAcrobat readerまたはFirefox等のビューアでブラウザ上に表示させることもできるが、ダウンロードダイアログを表示してPDFファイルをダウンロードさせることもできる。
もちろんPDFファイルのファイル名は指定できるが、場合によってはおかしくなる。
基本的な使い方と問題
mPDFを使用するには、mPDFを任意のディレクトリに設置し、呼び出し元でincludeして下記の様に処理する。
include('./MPDF57/mpdf.php'); // パスは環境に応じて変える $mpdf = new mPDF('ja', 'A4'); // 出力ファイル設定 $mpdf->writeHTML($data); // pdf内容をhtmlで突っ込む // 'sample.pdf'というファイル名でダウンロードさせる $mpdf->Output('sample.pdf', 'D');
このとき、$mpdf->Output();で指定するファイル名が一時ファイルのパスとなる為、同一ディレクトリのpermissionによって上手くいかないことがある(特に何らかのフレームワークを使用している場合)。
その為フルパス指定で任意のディレクトリに書き出すと安全だが・・・
$mpdf->Output('/var/www/html/pdf/sample.pdf', 'D');
などとした場合、ダウンロードされるpdfのファイル名は、
_var_www_html_pdf_sample.pdf
の様にパスを含んだものになってしまう。
原因
mpdf.phpの7480行付近(※バージョンによる)に、ファイル名の設定(レスポンスヘッダ)がある。
if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { // don't use length if server using compression header('Content-Length: '.strlen($this->buffer)); } header('Content-disposition: attachment; filename="'.$name.'"'); echo $this->buffer; break;
この$nameは$mpdf->Output();の第一引数をそのまま使用している為、ファイル名にパスが含まれてしまう。
ファイル名に関するオプションなどは無さそうなので、この部分の処理を変更するしかない。
パスを含まないように修正する
ヘッダのfilenameに期待するファイル名を記述すればいいので、次のようにした。
if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { // don't use length if server using compression header('Content-Length: '.strlen($this->buffer)); } /* --- ここから --- */ $wk_name = explode('/', $name); if (count($wk_name) > 1) { $name = $wk_name[count($wk_name) - 1]; } /* --- ここまで --- */ header('Content-disposition: attachment; filename="'.$name.'"'); echo $this->buffer; break;
入力されたパスを’/’でexplodeし、末尾の文字列をファイル名としている。
これでどの階層にあってもフルパス指定でダウンロードできる。