今日も備忘録です。
このドキュメントについて
下記2点について記載していきます。
- PDFをダウンロード、ビュー表示させる方法
- OpenPDFを利用したPDF作成方法
※以下File操作系のクラスやメソッドについては、事前知識として必要
①:FileInputStream/FileOutputStreamクラス
②:Filesクラス
③:Pathクラスなど
実行環境
・Java17
・springboot 3.0.2
実装
①PDFをダウンロード、ビュー表示させる
PDFをダウンロードさせたり、ビュー表示させる方法は大きく分けて2つある。
方法① : HttpServletResponseを利用する
var response = new HttpServletResponse();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline");
try(var inputStream = new BufferedInputStream(new FileInputStream(Fileクラス));
var res = response.getOutputStream()) {
res.write(inputStream.readAllBytes());
} catch (IOException e) {
throw new RuntimeException("ファイル操作で問題発生", e);
}
説明:
-
HttpServletResponseにContentTypeをpdfで設定する
-
1に合わせてContent-Dispositionに"inline"を設定する
inlineは、ダウンロードではなくビューを表示する設定 -
HttpServletResponseの出力ストリームを取得して、PDFのバイトデータを書き込む
※レスポンスの返却とかは不要
方法② : ResponseEntityを利用する
public ResponseEntity<byte[]> otherPdfDl(HttpServletResponse response) {
var input = Paths.get("pdfを置いているパス");
var respHeader = new HttpHeaders();
respHeader.setContentType(MediaType.APPLICATION_PDF);
respHeader.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=sample.pdf");
try (var inputStream = new BufferedInputStream(new FileInputStream(Fileクラス))) {
return new ResponseEntity<byte[]>(inputStream.readAllBytes(), respHeader, HttpStatus.OK);
} catch (IOException e) {
throw new RuntimeException("ファイル操作で問題発生", e);
}
}
説明:
-
HttpHeadersクラスをインスタンス化する
-
ContentTypeをpdfを設定する
-
2に合わせてContent-Dispositionに"attachment"を設定する
attachmentは、ダウンロードする設定 -
ResponseEntityをインスタンス化し、引数に設定したヘッダー情報、PDFのバイトデータ、ステータスを設定する
出来上がったPDFを表示、ダウンロードさせるだけなら上記でOK!
②OpenPDFを利用してPDFを作成する
// gradle
implementation group: 'org.xhtmlrenderer', name: 'flying-saucer-pdf-openpdf', version: '9.1.11'
Path pdfTempFile = null;
try {
pdfTempFile = Files.createTempFile("temp", ".pdf");
} catch (IOException e) {
throw new RuntimeException("一時ファイル作成でエラーが発生しました", e);
}
var document = new Document();
PdfWriter pdfWriter = null;
try {
pdfWriter = PdfWriter.getInstance(document, new BufferedOutputStream(new FileOutputStream(pdfTempFile.toFile())));
var baseFont = BaseFont.createFont("HeiseiMin-W3", "UniJIS-UCS2-H", BaseFont.NOT_EMBEDDED);
// タイトル用
var titleFont = new Font(baseFont, 20f, Font.ITALIC, Color.RED);
// 本文用
var font = new Font(baseFont, 12f, java.awt.Font.PLAIN, Color.BLACK);
document.open();
document.add(new Paragraph("タイトル", titleFont));
document.add(new Paragraph("内容", font));
document.close();
pdfWriter.close();
} catch (FileNotFoundException e) {
throw new RuntimeException("ファイルが存在しません", e);
} catch (DocumentException e) {
throw new RuntimeException("ドキュメント操作でエラーが発生しました", e);
} catch (IOException e) {
throw new RuntimeException("ファイル操作でエラーが発生しました", e);
}
説明:
-
作成したPDFを一時的に置いておける一時ファイルを作成する
Files.createTempFile(prefix, suffix) -
pdfWriterとdocumentのインスタンスを取得する
・pdfWriter:PDFドキュメントに対して直接書き込むためのAPIを提供
・document:PDFドキュメントを作成するためのベースクラス -
PDFへの書き込みで日本語が利用できないので、利用できるように設定
・UniJIS-UCS2-Hこれを設定することで、PDFに日本語が表示できる -
documentに内容をaddしていく、この時に第二引数にfontを設定
-
pdfWriterとdocumentをcloseする
・closeする順番が違うと、PDFファイルに必要なすべての情報が書き込まれていないため、エラーが起こる。documentからcloseする -
1で作成した一時ファイルにpdfが作成されているので、そのパスを使って後の処理をすれば、ダウンロードでもビュー表示でも可能
PDF作成の注意点
-
基本的にそのままでは日本語が利用できない。
例えば、ファイル名でも日本語が利用できないので、URLEncoder.encode()を利用して、エンコードしてあげる必要がある。 -
htmlを読み込んでPDFに落とし込む時は、ITextRendererを利用する必要がある?
今回紹介したやり方ではhtmlをPDFにはめ込むことができなかった。
ITextRendererを利用すると簡単にhtmlをはめこめた。
var render = new ITextRenderer();
render.setDocumentFromString(stringHtml);
render.layout();
render.createPDF(res);
まとめ
バイトデータをレスポンスに設定して返却する方法とHttpServletResponseに直接書き込む方法があることを学びました。
また、ビュー表示やダウンロードの方法やファイル名などに日本語を利用する時は、URLエンコードしないといけないことも学べました。
PDF作成やダウンロードの処理について、もっと簡単なやり方もあれば教えてほしいです。