今回も引き続き、ファイルアップロード・ダウンロード機能の実装について述べる。ここでは、具体的なサンプルプログラムのソースコードを共有する。
前提条件
下記記事を参照のこと。
Spring BootのWEB画面上でファイルアップロード・ダウンロード機能を実装してみた(完成イメージと前提条件)前回は、Spring Bootのmybatisを利用して、「BLOB」「CLOB」を含むテーブルへのデータ追加・データ参照を行った。今回...
作成したサンプルプログラムの内容
なお、上図の赤枠は、下記記事に記載したソースコードと比較し、変更になったソースコードを示す。赤枠のソースコードについては今後記載する。
Spring Bootで、OracleのテーブルにBLOB,CLOBのカラムを含む場合のOracle接続を実装してみたOracleのデータ型に、大量のデータやバイナリデータを格納できる「BLOB」「CLOB」がある。「BLOB」にはバイナリデータ、「CL...
ファイルデータ(file_data)テーブルにアクセスするMapperクラスは以下の通り。今回必要なfindAllメソッド・getMaxIdメソッドを追加している。
package com.example.demo; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; @Mapper public interface FileDataMapper { /** * ファイルデータテーブル(file_data)から全件取得する * @return ファイルデータテーブル(file_data)のデータリスト */ @Select("SELECT id, file_path as filePath, file_obj as fileObj " + " FROM file_data ORDER BY id asc") List<FileData> findAll(); /** * 指定したIDをもつファイルデータテーブル(file_data)のデータを取得する * @param id ID * @return ファイルデータテーブル(file_data)の指定したIDのデータ */ @Select("SELECT id, file_path as filePath, file_obj as fileObj " + " FROM file_data WHERE id = #{id}") FileData findById(Long id); /** * ファイルデータテーブル(file_data)の最大値IDを取得する * @return ファイルデータテーブル(file_data)の最大値ID */ @Select("SELECT NVL(max(id), 0) as maxId FROM file_data") long getMaxId(); /** * 指定したファイルデータテーブル(file_data)のデータを追加する * @param fileData ファイルデータテーブル(file_data) */ @Insert("INSERT INTO file_data ( id, file_path, file_obj ) " + " VALUES ( #{id}, #{filePath}, #{fileObj} )") void insert(FileData fileData); }
「CODE×CODE」は、需要の高い技術(AWS, Python等)を習得できるプログラミングスクールスクールだった近年、さまざまな会社でクラウド(特にIaaSやPaaSのパブリッククラウド)の需要が非常に高まっていて、クラウドサービスによるシステム開...
また、ファイルデータ(file_data)テーブルにアクセスするMapperクラスを利用するコントローラクラスは以下の通り。ここではファイルアップロード・ファイルダウンロード処理も記載している。
ファイルアップロード処理(addメソッド)内では引数のMultipartFileオブジェクトからファイルオブジェクトを取得後、ファイルデータテーブルへのデータ追加を行っている。また、ファイルダウンロード処理(downloadメソッド)内では指定したIDのデータ取得後、HttpServletResponseクラスのwriteメソッドでダウンロード出力を行っている。
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 画面遷移先(nullを返す) */ @RequestMapping("/download") public String download(@RequestParam("id") String id , HttpServletResponse response){ //ダウンロード対象のファイルデータを取得 FileData data = fileDataMapper.findById(Long.parseLong(id)); //ファイルダウンロードの設定を実施 //ファイルの種類は指定しない response.setContentType("application/octet-stream"); response.setHeader("Cache-Control", "private"); response.setHeader("Pragma", ""); response.setHeader("Content-Disposition" ,"attachment;filename=\"" + getFileName(data.getFilePath()) + "\""); //ダウンロードファイルへ出力 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; } }
サラリーマン型フリーランスSEという働き方でお金の不安を解消しよう先日、「サラリーマン型フリーランスSE」という働き方を紹介するYouTube動画を視聴しましたので、その内容をご紹介します。 「サ...
さらに、一覧画面・入力画面のソースコード内容は以下の通り。ファイルアップロードを行うファイルの選択は、inputタグのtype=”file”で指定していて、nameタグの内容をコントローラクラスの引数のMultipartFileオブジェクトとして渡している。
<!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> <!-- ダウンロードボタンを表示 --> <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> </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>
<!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>入力画面</title> </head> <body> <p>入力ファイルを指定し、「登録」ボタンを押下してください。</p><br/> <form method="post" enctype="multipart/form-data" th:action="@{/add}"> ファイル : <input type="file" name="upload_file" /><br/><br/> <input type="submit" value="送信" /> <input type="button" value="戻る" onclick="history.back();" /> </form> </body> </html>
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-upload-download-2/demo
要点まとめ
- ファイルアップロード処理では、HTMLファイルでinputタグのtype=”file”を指定し、nameタグの内容をコントローラクラスの引数のMultipartFileオブジェクトとして渡すことで、ファイルオブジェクトを連携できる。
- ファイルダウンロード処理では、HttpServletResponseオブジェクトのwriteメソッドで、ダウンロード出力処理を行えばよい。