##やりたいこと
TCPDFとFPDIを利用して、Web上でユーザが入力した情報をテンプレートのPDFに文字として埋め込む機能を実装した。
実際に作成したPDFを一旦ブラウザ上で表示するようにする。
(必要事項入力→作成ボタン押す→文字を埋め込んだPDFをブラウザで表示)
##起きた問題
実際に動作を確認した時、以下のブラウザでそれぞれ変な動作になった。
chrome
・ブラウザのPDFビューワーに表示されるファイル名が、PDFを表示させているソースコードのファイル名になる。(XXX.phpみたいな)
・ダウンロードボタンを押した時のデフォルトファイル名も、XXX.phpのようなソースコードのファイル名になる。
・実際にダウンロードされるファイルが、HTML形式のコード。
Edge
・表示されるPDFのファイル名は問題ないが、ビューワーのダウンロード機能でダウンロードすると、デフォルトのファイル名が「無題.pdf」になる。
今回、ブラウザ上に作成したPDFを表示させるのに、TCPDFのOutputメソッドを出力モード「I」(ブラウザのビューワーで出力)を利用した。
引数として表示させたいファイル名を指定すれば、Content-Dispositionのfilenameに指定したファイル名が設定されると思っていたが・・・想定していた通りに動作しなかった。
ちなみにfirefoxでは正しく動作した。ありがとうfirefox。
##解決策
一番簡単なのは、作成ボタンを押したら、PDFファイルを一旦サーバ上に保存し、それを直接表示させるようなURLを生成して出力させる方法かな。と、直感では思ったが、今回はファイルを保存しない方法で解決してみた。
####ビューワー上で表示されるファイル名
URLがビューワーで表示させたいファイル名になればいいので、URLはファイル名に設定し、実際に走らせたいPHPファイルに内部で書き換えてしまう。
//PDF作成
$pdf = $pdf->Output('PDFファイル名', 'S');
header("Location:URL"); //ここでXXX.pdfみたいにファイル名を記述
RewriteEngine On
RewriteRule ^.*\.pdf$ 表示処理をするPHPファイル名
####ダウンロードする時のファイル名を正しく設定
上記の.htaccessで呼び出したPHPファイル内でPDFの表示処理をさせる。
PDF作成時からファイルを跨いでの処理のため、作成したPDFを一旦セッションに保持させる。その際、TCPDFのOutputの出力モードはSを指定する。
//PDF作成
//出力モード「S」:PDFを文字列として出力する。
$pdf = $pdf->Output('PDFファイル名', 'S');
session_start();
$_SESSION["pdf"] = $pdf; //セッションに退避
header("Location:URL"); //ここでXXX.pdfみたいにファイル名を記述
あとは表示処理側のPHPで退避したセッションから取り出す。
ダウンロード時のファイル名はContent-Dispositionのfilenameに設定すればOK。
session_start();
$data = $_SESSION["pdf"];
header('Content-Type: application/pdf');
header('Content-Disposition: inline;filename=DL時のファイル名');
echo($data);
exit;
これでchrome、Edge共にダウンロード時のデフォルトファイル名が正しく設定された上、chromeではきちんと作成したPDFファイルがダウンロードされた。
だいぶ回りくどい方法になってしまったが、PDFを保存したり、消したりといったことを考えなくていいので楽といえば楽だったかなと。
IEだとinline指定時にfilenameが正しく設定されないという話はちらほら見かけたが、chromeでこのような現象に出くわしてる例が全くと言っていいほど見かけず、四苦八苦した。
##参考
今回の解決方法はここの方法をガッツリ適用させました。
・サーバ側で作成したPDFの表示とクライアントPCへの保存 - 闘うITエンジニアの覚え書き
https://www.magata.net/memo/?%A5%B5%A1%BC%A5%D0%C2%A6%A4%C7%BA%EE%C0%AE%A4%B7%A4%BFPDF%A4%CE%C9%BD%BC%A8%A4%C8%A5%AF%A5%E9%A5%A4%A5%A2%A5%F3%A5%C8PC%A4%D8%A4%CE%CA%DD%C2%B8