前回は、Sping BootのWEB画面上で、ファイルアップロード・ファイルダウンロード機能について記載したが、今回は、PDFの場合のみPDFプレビューを行うようにしたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
Spring BootのWEB画面上でファイルアップロード・ダウンロード機能を実装してみた(ソースコード編)今回も引き続き、ファイルアップロード・ダウンロード機能の実装について述べる。ここでは、具体的なサンプルプログラムのソースコードを共有する...
完成イメージ
ここでは、完成した画面イメージの共有を行う。
Spring Bootアプリケーションを起動し、「http:// (ホスト名):(ポート番号)」とアクセスした場合の初期表示は以下の通りとする。

「PDFプレビュー」ボタンを押下すると、以下のように、別画面にPDFプレビュー画面が表示される。


作成したサンプルプログラムの内容
作成したサンプルプログラムの構成は以下の通り。なお、下図の赤枠は、前提条件に記載した記事と変更になったソースコードを示しており、今後記載する。

一覧画面を表示するプログラムは以下の通り。PDFの場合は「PDFプレビュー」ボタンを、それ以外の場合は「ダウンロード」ボタンを表示するようにしている。PDFの場合は、window.open関数を呼んでいて、新規画面を開くようにしている。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>一覧画面</title>
</head>
<body>
ファイルデータテーブル(file_data)の全データ<br/><br/>
<table border="1" cellpadding="5">
<tr>
<th>ID</th>
<th>ファイルパス</th>
<th></th>
</tr>
<tr th:each="obj : ${fileDataList}">
<td th:text="${obj.id}"></td>
<td th:text="${obj.filePath}"></td>
<td>
<!-- ダウンロードボタンを表示 -->
<!-- PDFファイルの場合 -->
<div th:if=${#strings.endsWith(obj.filePath,'.pdf')}>
<input type="button" value="PDFプレビュー"
th:onclick="'window.open(\'/download?id='
+ ${obj.id} + '\', target=\'_blank\');'" />
</div>
<!-- PDFファイル以外の場合 -->
<div th:unless=${#strings.endsWith(obj.filePath,'.pdf')}>
<form action="#" method="get"
th:action="@{/download(id=${'__${obj.id}__'})}"
th:method="download" >
<input type="hidden" name="_method" value="download" />
<input type="submit" value="ダウンロード" />
</form>
</div>
</td>
</tr>
</table>
<br/><br/>
<form method="post" th:action="@{/to_add}">
<input type="submit" value="データ追加" /><br/><br/>
<input type="button" value="閉じる" onclick="window.close();" />
</form>
</body>
</html>さらに、ダウンロード処理を含むコントローラクラスのプログラムは以下の通り。downloadメソッドが変更点である。PDFとそれ以外で処理を分け、PDFの場合は、ContentTypeを「application/pdf」に設定し「Content-Disposition」をinlineにすることで、(新しく開いた画面に)PDFプレビュー画面を開くようにしている。
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
@Controller
public class DemoController {
/**
* ファイルデータテーブル(file_data)へアクセスするMapper
*/
@Autowired
private FileDataMapper fileDataMapper;
/**
* ファイルデータ一覧表示処理
* @param model Modelオブジェクト
* @return 一覧画面
*/
@RequestMapping("/")
public String index(Model model){
//ファイルデータテーブル(file_data)を全件取得
List<FileData> list = fileDataMapper.findAll();
model.addAttribute("fileDataList", list);
//一覧画面へ移動
return "list";
}
/**
* ファイルデータ登録画面への遷移処理
* @return ファイルデータ登録画面
*/
@PostMapping("/to_add")
public String to_add(){
return "add";
}
/**
* ファイルデータ登録処理
* @param uploadFile アップロードファイル
* @return ファイルデータ一覧表示処理
*/
@PostMapping("/add")
@Transactional(readOnly = false)
public String add(@RequestParam("upload_file") MultipartFile uploadFile){
//最大値IDを取得
long maxId = fileDataMapper.getMaxId();
//追加するデータを作成
FileData fileData = new FileData();
fileData.setId(maxId + 1);
fileData.setFilePath(uploadFile.getOriginalFilename());
try{
fileData.setFileObj(uploadFile.getInputStream());
}catch(Exception e){
System.err.println(e);
}
//1件追加
fileDataMapper.insert(fileData);
//一覧画面へ遷移
return "redirect:/to_index";
}
/**
* 追加完了後に一覧画面に戻る
* @param model Modelオブジェクト
* @return 一覧画面
*/
@GetMapping("/to_index")
public String toIndex(Model model){
return index(model);
}
/**
* ファイルダウンロード処理
* @param id ID
* @param response HttpServletResponse
* @return 画面遷移先
*/
@RequestMapping("/download")
public String download(@RequestParam("id") String id
, HttpServletResponse response){
//ダウンロード対象のファイルデータを取得
FileData data = fileDataMapper.findById(Long.parseLong(id));
//ダウンロード対象のファイルデータがnullの場合はエラー画面に遷移
if(data == null || data.getFileObj() == null){
return "download_error";
}
//PDFの場合
if(data.getFilePath().endsWith(".pdf")){
//PDFプレビューの設定を実施
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline;");
}else{
//ファイルダウンロードの設定を実施
//ファイルの種類は指定しない
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition"
,"attachment;filename=\"" + getFileName(data.getFilePath()) + "\"");
}
//その他の設定を実施
response.setHeader("Cache-Control", "private");
response.setHeader("Pragma", "");
try(OutputStream out = response.getOutputStream();
InputStream in = data.getFileObj()){
byte[] buff = new byte[1024];
int len = 0;
while ((len = in.read(buff, 0, buff.length)) != -1) {
out.write(buff, 0, len);
}
out.flush();
}catch(Exception e){
System.err.println(e);
}
//画面遷移先はnullを指定
return null;
}
/**
* ファイルパスからファイル名を取得する
* @param filePath ファイルパス
* @return ファイル名
*/
private String getFileName(String filePath){
String fileName = "";
if(filePath != null && !"".equals(filePath)){
try{
//ファイル名をUTF-8でエンコードして指定
fileName = URLEncoder.encode(new File(filePath).getName(), "UTF-8");
}catch(Exception e){
System.err.println(e);
return "";
}
}
return fileName;
}
}その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-pdf-preview/demo
要点まとめ
- ContentTypeを「application/pdf」に設定し、「Content-Disposition」をinlineにすることで、PDFプレビュー表示が行える。







