質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CodeIgniter

CodeIgniterは、PHP向けオープンソースのWebアプリケーションフレームワークです。CodeIgniterは覚える構文が少なく、自由度も高いため、PHPを理解していれば構築が簡単です。

Q&A

解決済

1回答

9073閲覧

PDFを表示してから保存する方法

SystemAjisai

総合スコア171

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CodeIgniter

CodeIgniterは、PHP向けオープンソースのWebアプリケーションフレームワークです。CodeIgniterは覚える構文が少なく、自由度も高いため、PHPを理解していれば構築が簡単です。

0グッド

1クリップ

投稿2018/02/21 07:49

編集2018/02/22 01:18

前提・実現したいこと

CodeIgniter2を使ったWebシステムで、PDFを作るプログラムを作成しています。
目指している挙動は

  1. ユーザがダウンロードボタンを押す
  2. PHPでPDFを作成
  3. 作成したPDFを別ウインドウで表示
  4. 保存したければ保存してもらう

となります。
対象ブラウザはGoogleChromeのみです。
4.のPDFの保存は、ブラウザ上でPDFを表示した際に「ダウンロード」というアイコンが出るので、
その機能を使ってもらう予定にしています。
イメージ説明
※指の形のカーソルが出てるアイコンの事です

発生している問題・エラーメッセージ

3のPDF表示までは上手くいっていますが、その後ダウンロードアイコンを押すと、
「失敗-ネットワークエラー-」と表示されてしまい、ダウンロードできません。
イメージ説明

表示できているのにダウンロードで失敗する場合、どこを疑えばいいのかもよくわかっていない状態です。
ネットワークエラーと表示されているので何かしらPHPのプログラムに問題があるのでは?と調査しているのですが、有用な情報を見つけることができません。

また、ブラウザ上に表示されるファイル名(画像で塗りつぶしている箇所)について
下記ソースの通り「sample.pdf」になるのを期待していますが、実際にはパラメータ名(※1)になってしまっています。
ここに拡張子が付いていないのが問題かと思い、試しにパラメーターに.pdfを付けてみましたが、結果は同じでした。

どうすれば表示したPDFを保存できるようになるのでしょうか。
ブレイクポイントを設定してダウンロードアイコンを押してみましたが、PHPが呼ばれていなかったため、最初にPDFを表示した時のレスポンスの設定が怪しいと思い、該当箇所のソースを載せています。
見当違いの場合は、お手数ですが指摘して頂ければ助かります。

(※1)
CodeIgniterを使用しているので、パラメーターを渡す場合urlの関数名の後ろに/paramという形で加えます。

http://~~~/download/aaa

の場合、表示されるファイル名が「aaa」になってしまいます。

該当のソースコード

以下がPDFを返している処理です。

php

1function download($param){ 2 : 3 : 4 $html = $this->load->view(PDF化したいviewのパス, $result, TRUE); 5 $pdf = new Knp\Snappy\Pdf(wkhtmltopdfのパス); 6 $pdf->setOption('encoding', 'utf-8'); 7 $this->output 8       ->set_header('Content-Disposition: inline; filename="sample.pdf"') 9       ->set_content_type("application/pdf") 10       ->set_output($pdf->getOutputFromHtml($html)); 11}

試したこと

その1
PDFに問題があるのか調査するため、Content-Dispositionをattachmentにしてどうなるか試してみました。

php

1function download($param){ 2 : 3 : 4 $this->output 5 ->set_header('Content-Disposition: attachment; filename="sample.pdf"') 6 ->set_content_type("application/pdf") 7 ->set_output($pdf->getOutputFromHtml($html)); 8}

ファイルがダウンロードされ、開くこともできました。
一応ダウンロードアイコンを押してみましたが、ちゃんとダウンロードできました。

その2
作成したPDFは実体のファイルになっていないのが原因ではないかと思い、
一旦サーバーに実ファイルを作成して、ファイルをダウンロードするようにしてみました。

php

1function download($param){ 2 : 3 $this->load->helper('file'); 4 $data = read_file("作成したPDFファイルのパス"); 5 6 $this->output 7 ->set_header('Content-Disposition: inline; filename="sample.pdf"') 8 ->set_content_type("application/pdf") 9 ->set_output($data); 10}

実ファイルを作成する前と同様、
ファイルの内容は表示されるけど、ダウンロードを押すとネットワークエラーになってしまいました。
またブラウザ上に表示されるファイル名もsample.pdfではなくパラメーター名になってしまいました。

(追記) 解決した設定

asahina1979さんにご指摘頂いて、作成したPDFがキャッシュされるように指定を加えました。

php

1 $this->output 2     ->set_content_type("application/pdf") 3 ->set_header('Content-Disposition: inline; filename=sample.pdf') 4// 追加ここから 5 ->set_header('Last-Modified: Fri Jan 01 2010 00:00:00 GMT') 6 ->set_header('Expires: Fri Jan 01 2019 00:00:00 GMT') // お試しで未来日を入れる 7 ->set_header('Cache-Control: private, max-age=86400') // お試しで1日にしてみる 8// 追加ここまで 9 ->set_output($pdf->getOutputFromHtml($html));

インラインで表示後ダウンロードアイコンを押して正常にダウンロードされるようになりました。
ファイル名についてもキャッシュの設定を加えることで反映されるようになり、sample.pdfとしてダウンロードできました。
ありがとうございました!

補足情報(FW/ツールのバージョンなど)

PHP 7.1
CodeIgniter 2
GoogleChrome
wkhtmltopdf(PDF作成用)
Snappy(PDF作成の元ネタHTML作成用)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/02/21 14:03

認証エラーじゃねーの? 開発ツールでステータスコードを見よう
SystemAjisai

2018/02/21 23:08

すみません…どこを見ればいいのでしょうか。F12を押したら出てくる開発ツールを見てみたのですが、ダウンロードアイコンを押した時にNetworkのタブに何も記録されませんし、Consoleにも何も出ませんでした。
退会済みユーザー

退会済みユーザー

2018/02/21 23:13

開発ツールをPDFの開いているタブで起動してますよね?それで出ないならサーバーログ(httpdのアクセスログやエラーログ)を確認してみてください
SystemAjisai

2018/02/21 23:30

開発ツールはPDFを開くタブで起動しました。Apacheを使っているのでそのログを確認してみました。インラインでPDFを表示した時にはaccess.logにログが残り、ステータスが200になっていました。そのあとダウンロードアイコンを押した時には、access.logにもerror.logにも何も記録されませんでした。
SystemAjisai

2018/02/22 00:08

関係ないかもしれませんが、chromeのダウンロードリストから失敗したダウンロードを「再開」としてみたら、PDF作成のプログラムが呼び出され、access.logにもステータス200として記録されました。ダウンロードされたファイルはパラメータ名のみで拡張子がついていませんが、手動で.pdfを足したらちゃんと正しい内容のファイルがダウンロードできていました。
退会済みユーザー

退会済みユーザー

2018/02/22 00:09

あとはキャッシュをマイナスとかゼロ設定にしています?
SystemAjisai

2018/02/22 00:29

キャッシュというのは何も設定していませんでした。動的に作ってるPDFだけどURL一緒だから同じものとして扱われて再取得が行われないのでは?という意味かなと思って、PDFを返す時のset_headerでCache-Controlをno-store,no-cashe、Apacheのhttpd.confにもキャッシュさせないための設定を調べて入れてみたのですが、同じ状態になってしまいました。。。
退会済みユーザー

退会済みユーザー

2018/02/22 00:32

通信してないということはキャッシュからとってきてるのではとおもったから無効化が原因なのではと思った次第(なんで 来年指定などで)
SystemAjisai

2018/02/22 00:52

すみません!真逆にとらえてしまいました! レスポンスのset_headerでキャッシュを残す設定というのを調べて入れて、さっき追加したApacheのキャッシュさせない設定も削除したら無事にダウンロードすることができました!! おまけに設定しても無視されていたfilenameの指定も受け付けてもらうことができました。ベストアンサーにしたいので回答の方に記載して頂けると嬉しいです。直した内容は質問文に追記します。本当にありがとうございます!
guest

回答1

0

ベストアンサー

通信ログがないということはキャシュから取得していると思われるので
キャッシュを未来日に設定してはいかがでしょうか?

投稿2018/02/22 03:10

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SystemAjisai

2018/02/22 03:59

本当に色々とありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問