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

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

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

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

3583閲覧

postgresql + Spring でDBに保存した画像を表示させたい

mimi_129

総合スコア63

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2021/07/04 03:14

編集2021/07/10 08:49

前提・実現したいこと

input type="file"で送ったマルチパートをDBに保存し、出力したいです。

editで画像を選択

editCheckで選択された画像を表示

DBにinsert

detailで保存された画像を表示といった流れです。

DBViwerを見るとINSERTはできている(?)みたいなのですが、
detailで表示ができません。(Eclipse上で確認をしようとするとエラーが出る)
イメージ説明

byte自体は入っているみたいなので、INSERTはできている様なのですが。。
イメージ説明

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

syntax error at or near ">>"

KeiyakuMaster.java

package com.example.demo.keiyakuMaster; @Data @Entity @Table(name = "keiyakumaster") public class KeiyakuMaster implements Serializable { @Getter @Setter @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column private long id; @Getter @Setter @Column private int keiyakuid; @Getter @Setter @Column private int shohinid; @Getter @Setter @Column private int price; @Getter @Setter @Column private int kinri; @Getter @Setter @Column private String returnlimit; @Getter @Setter @Column private int clientid; @Getter @Setter @Column private int koinid; @Getter @Setter @Column private int shoninflg; @Getter @Setter @OneToOne @JoinColumn(name = "shohinid", referencedColumnName = "shohinid", insertable = false, updatable = false) private ShohinMaster shohinmaster; @Getter @Setter @Lob @Type(type = "org.hibernate.type.BinaryType") @Column(name="filedata") private byte[] filedata; @Getter @Setter @Column private String filename; }

edit.html

<!doctype html> <html xmlns:th="http://www.thymeleaf.org"> <head th:replace="~{layout/component :: head('システム管理者情報一覧')}"></head> <script> function deleteCheck() { var id = $('#id').val(); var result = window.confirm('本当に削除してもよろしいですか?'); if(result) { document.location.href = '/keiyakuMaster/delete?id=' + id; } } function returnDetail() { document.location.href = '/keiyakuMaster/returnDetail'; return false; } </script> <body> <th:block th:replace="~{layout/component :: header}"></th:block> <div class="container"> <th:block th:replace="~{layout/component :: container_top('契約一覧')}"></th:block> <div class="row justify-content-start"> <form method="post" th:action="@{/keiyakuMaster/editCheck}" th:object="${keiyakuMasterForm}" enctype="multipart/form-data"> <table class="table table-bordered"> <tr> <td><label>添付ファイル</label></td> <td> <input type="file" name="filedata"> </td> </tr> </table> <div class="mb-3"> <input type="submit" value="確認" class="btn btn-outline-secondary"> <a href="/keiyakuMaster/list" class="btn btn-outline-secondary" th:if="${#strings.isEmpty(keiyakuMasterForm.id)}">戻る</a> <input type="button" value="戻る" class="btn btn-outline-secondary" onClick="returnDetail();" th:if="${!#strings.isEmpty(keiyakuMasterForm.id)}"> <input type="button" value="削除" class="btn btn-outline-secondary" onClick="deleteCheck();" th:if="${!#strings.isEmpty(keiyakuMasterForm.id)}"> </div> </form> </div> </div> <footer th:replace="~{layout/component :: footer}"></footer> </body> </html>

editCheck.html

editCheck.html

1<!doctype html> 2<html xmlns:th="http://www.thymeleaf.org"> 3<head th:replace="~{layout/component :: head('契約一覧')}"></head> 4<script> 5function returnEdit() { 6 document.location.href = '/keiyakuMaster/returnEdit'; 7 8 return false; 9} 10</script> 11<body> 12<th:block th:replace="~{layout/component :: header}"></th:block> 13<div class="container"> 14 <th:block th:replace="~{layout/component :: container_top('契約一覧')}"></th:block> 15 <div class="row justify-content-start"> 16 <form method="post" th:action="@{/keiyakuMaster/finish}" th:object="${keiyakuMasterForm}"> 17 <table class="table table-bordered"> 18 19 <tr> 20 <td> 21 <label>添付ファイル</label> 22 </td> 23 <td> 24 <img th:src="${'data:image/png;base64,'+image}" alt=""> 25 <input type="hidden" name="filedata" th:field="*{filedata}"> 26 <input type="hidden" name="filename" th:field="*{filename}"> 27 </td> 28 </tr> 29 </table> 30 <!-- <img th:src="${'data:image/png;base64,'+image}" alt=""> --> 31 <div class="mb-3"> 32 <input type="submit" value="送信" class="btn btn-outline-secondary"> 33 <input type="button" value="戻る" class="btn btn-outline-secondary" onClick="returnEdit()"> 34 </div> 35 </form> 36 </div> 37</div> 38<footer th:replace="~{layout/component :: footer}"></footer> 39</body> 40</html>

detail.html

detail.html

1<!doctype html> 2<html xmlns:th="http://www.thymeleaf.org"> 3<head th:replace="~{layout/component :: head('契約一覧')}"></head> 4<body> 5<th:block th:replace="~{layout/component :: header}"></th:block> 6<div class="container"> 7 <th:block th:replace="~{layout/component :: container_top('契約一覧')}"></th:block> 8 <div class="row justify-content-start"> 9 <form method="post" th:action="@{/keiyakuMaster/finish}" th:object="${keiyakuMasterForm}"> 10 <table class="table table-bordered"> 11 12 <tr> 13 <td> 14 <label>添付ファイル</label> 15 </td> 16 <td> 17 <img th:src="${'data:image/png;base64,'+image}" alt=""> 18 <input type="hidden" name="filedata" th:field="*{filedata}"> 19 </td> 20 </tr> 21 </table> 22 <div class="mb-3"> 23 <a th:href="@{'/keiyakuMaster/edit?id=' + ${keiyakuMasterForm.id}}" class="btn btn-outline-secondary">編集</a> 24 <a href="/keiyakuMaster/list" class="btn btn-outline-secondary">戻る</a> 25 </div> 26 </form> 27 </div> 28</div> 29<footer th:replace="~{layout/component :: footer}"></footer> 30</body> 31</html>

KeiyakuMasterController.java

KeiyakuMasterController.java

1 @RequestMapping(value = "/keiyakuMaster/detail") 2 private String detail(@RequestParam(name = "id", required = false) Long id, 3 @ModelAttribute("keiyakuMasterForm") KeiyakuMasterForm keiyakuMasterForm, HttpSession session,Model model) { 4 5 if(id == null) { 6 // 新規登録 7 }else { 8 // 更新 9 var keiyakuMaster =keiyakuMasterRepository.findById(id).get(); 10 11 BeanUtils.copyProperties(keiyakuMaster, keiyakuMasterForm); 12 13 keiyakuMasterForm.setId(id); 14 keiyakuMasterForm.setKoinname(koinMasterService.findByKoinid(keiyakuMaster.getKoinid()).getKoinname()); 15 keiyakuMasterForm.setClientname(clientMasterService.findByClientid(keiyakuMaster.getClientid()).getName()); 16 keiyakuMasterForm.setShohinname(shohinMasterService.findByShohinid(keiyakuMaster.getShohinid()).getName()); 17 18 model.addAttribute("image", Base64.getEncoder().encodeToString(keiyakuMaster.getFiledata())); 19 } 20 21 session.setAttribute("keiyakuMasterForm",keiyakuMasterForm); 22 23 return "/keiyakuMaster/detail"; 24 } 25 26 @RequestMapping(value = "/keiyakuMaster/edit") 27 private String edit(Model model, @RequestParam(name = "id", required = false) Long id, @ModelAttribute("keiyakuMasterForm") KeiyakuMasterForm keiyakuMasterForm, HttpSession session) { 28 29 if(id == null) { 30 // 新規登録 31 }else { 32 // 更新 33 var keiyakuMaster =keiyakuMasterRepository.findById(id).get(); 34 35 BeanUtils.copyProperties(keiyakuMaster, keiyakuMasterForm); 36 37 keiyakuMasterForm.setId(id); 38 keiyakuMasterForm.setKoinname(koinMasterService.findByKoinid(keiyakuMaster.getKoinid()).getKoinname()); 39 keiyakuMasterForm.setClientname(clientMasterService.findByClientid(keiyakuMaster.getClientid()).getName()); 40 keiyakuMasterForm.setShohinname(shohinMasterService.findByShohinid(keiyakuMaster.getClientid()).getName()); 41 } 42 43 this.setShohinSelectTag(model); 44 this.setClientSelectTag(model); 45 this.setKoinSelectTag(model); 46 47 session.setAttribute("keiyakuMasterForm",keiyakuMasterForm); 48 49 return "/keiyakuMaster/edit"; 50 } 51 52 @RequestMapping("/keiyakuMaster/editCheck") 53 public String editCheck(@RequestParam("filedata") MultipartFile file, HttpSession session, @Validated @ModelAttribute KeiyakuMasterForm keiyakuMasterForm, BindingResult result, Model model) { 54 55 byte[] bytes = null; 56 57 try { 58 bytes = file.getBytes(); 59 } catch (IOException e) { 60 e.printStackTrace(); 61 } 62 63 String image = Base64.getEncoder().encodeToString(bytes); 64 65 keiyakuMasterForm.setFilename(StringUtils.cleanPath(file.getOriginalFilename())); 66 keiyakuMasterForm.setFiledata(bytes); 67 68 model.addAttribute("image", image); 69 70 keiyakuMasterForm.setShohinname(shohinMasterService.findByShohinid(keiyakuMasterForm.getShohinid()).getName()); 71 keiyakuMasterForm.setClientname(clientMasterService.findByClientid(keiyakuMasterForm.getClientid()).getName()); 72 keiyakuMasterForm.setKoinname(koinMasterService.findByKoinid(keiyakuMasterForm.getKoinid()).getKoinname()); 73 74 session.setAttribute("keiyakuMasterForm",keiyakuMasterForm); 75 76 77 return "/keiyakuMaster/editCheck"; 78 } 79 80 @PostMapping("/keiyakuMaster/finish") 81 public String finish(HttpSession session, @ModelAttribute("keiyakuMasterForm") KeiyakuMasterForm keiyakuMasterForm) { 82 83 var keiyakuMaster = new KeiyakuMaster(); 84 85 if(keiyakuMasterForm.getId() == null) { 86 int maxId = keiyakuMasterService.findByMaxKeiyakuId(); 87 88 keiyakuMasterForm.setId((long) 0); 89 keiyakuMasterForm.setKeiyakuid(maxId + 1); 90 } 91 92 BeanUtils.copyProperties(keiyakuMasterForm, keiyakuMaster); 93 94 this.keiyakuMasterService.save(keiyakuMaster); 95 96 return "/keiyakuMaster/finish"; 97 }

試したこと

ここに問題に対して試したことを記載してください。

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

イメージ説明
いただいたコメントを元に調査していたら、
editCheckにそもそもバイトが渡っていない?ようでした。。
イメージ説明
formクラスにバイトが渡っているのに。。?

ここにより詳細な情報を記載してください。

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

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

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

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

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

gpsoft

2021/07/04 11:50

editCheck()メソッドの中にある keiyakuMasterForm.setFiledata(bytes); が気になりました。 このbytesって、バイト配列だと思いますが、 それを <input type="hidden" name="filedata" th:field="*{filedata}"> ↑このhiddenに仕込む作戦ですよね? うまくいくかなぁ? KeiyakuMasterFormクラスの中に何か変換処理があるなら良いのですが、バイト配列をそのままhiddenにセットしたらどうなるのかな? ちょっと分かりません。 あと、スクショに載ってるimg要素のsrc属性の値は、PNG画像っぽくない気がしました。 先頭のb3JnLnNwcmluZ2ZyYW1ld29yay53ZWIの部分をbase64デコードしてみると、org.springframework.webという文字列になるので…。 解析の参考になれば幸いです。
KT001

2021/07/07 09:59

こちら、(画像部分だけで良いので)動作に必要な他クラスも、掲示することは可能でしょうか。 該当部分だけでも動作できるクラスがあれば、分かるかもしれません。
guest

回答1

0

ベストアンサー

postgresql + Spring でDBに画像を保存する、簡単なサンプルを作ってみました。
ポイントは、アップロード時のMultipartFileと、表示時のBase64エンコードです。

KeiyakuMaster.java

java

1@Getter 2@Setter 3@Entity 4@Table(name = "keiyakumaster") 5public class KeiyakuMaster { 6 7 @Id 8 @GeneratedValue(strategy = GenerationType.IDENTITY) 9 private Long id; 10 11 @Lob 12 @Type(type="org.hibernate.type.BinaryType") 13 private byte[] filedata; 14 15 @Column(name="contenttype") 16 private String contentType; 17 private String filename; 18}

index.html

html

1<!DOCTYPE html> 2<html xmlns:th="http://www.thymeleaf.org"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Image upload</title> 7</head> 8<body> 9 <th:block th:if="${#strings.isEmpty(filename)}"> 10 <form th:action="@{/}" th:object="${keiyakuMaster}" method="post" enctype="multipart/form-data"> 11 <input type="file" th:field="*{filedata}" accept="image/png, image/jpeg"><br> 12 <br> 13 <button>アップロードの確認へ</button> 14 </form> 15 </th:block> 16 <th:block th:unless="${#strings.isEmpty(filename)}"> 17 <p>以下の画像を、アップロードしてもよろしいですか?</p> 18 <form th:action="@{/save}" method="post" enctype="multipart/form-data"> 19 <button>画像のアップロード</button><br> 20 <br> 21 <input type="hidden" name="contentType" th:value="${contentType}"> 22 <input type="hidden" name="filename" th:value="${filename}"> 23 <input type="hidden" name="viewFiledata" th:value="${viewFiledata}"> 24 <img th:src="@{'data:' + ${contentType} + ';base64,'+${viewFiledata}}" alt=""> 25 </form> 26 </th:block> 27</body> 28</html> 29

result.html

html

1<!DOCTYPE html> 2<html xmlns:th="http://www.thymeleaf.org"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Image upload</title> 7</head> 8<body> 9 <p style="color:red">以下の画像が、アップロードされました</p> 10 <img th:if="!${#strings.isEmpty(filedata)}" th:src="@{'data:' + ${contentType} + ';base64,'+${filedata}}" alt=""> 11</body> 12</html>

KeiyakuMasterRepository.java

java

1@Repository 2public interface KeiyakuMasterRepository extends JpaRepository<KeiyakuMaster, Long> { 3}

KeiyakuMasterController.java

java

1@RequiredArgsConstructor 2@Controller 3public class KeiyakuMasterController { 4 5 private final KeiyakuMasterRepository keiyakuMasterRepository; 6 7 @GetMapping("/") 8 public String read(@ModelAttribute KeiyakuMaster keiyakuMaster) { 9 return "index"; 10 } 11 12 @PostMapping("/") 13 public String confirm(@RequestParam("filedata") MultipartFile filedata, Model model) throws IOException { 14 if (filedata.getContentType().startsWith("image/")) { 15 model.addAttribute("contentType", filedata.getContentType()); 16 } else { 17 model.addAttribute("keiyakuMaster", new KeiyakuMaster()); 18 return "index"; 19 } 20 model.addAttribute("filename", filedata.getOriginalFilename()); 21 model.addAttribute("viewFiledata", Base64.getEncoder().encodeToString(filedata.getBytes())); 22 return "index"; 23 } 24 25 @PostMapping("/save") 26 public String save( 27 @RequestParam("contentType") String contentType, 28 @RequestParam("filename") String filename, 29 @RequestParam("viewFiledata") String viewFiledata) throws IOException { 30 31 var keiyakuMaster = new KeiyakuMaster(); 32 if (contentType.startsWith("image/")) { 33 keiyakuMaster.setContentType(contentType); 34 } else { 35 keiyakuMaster.setContentType(""); 36 } 37 keiyakuMaster.setFilename(filename); 38 keiyakuMaster.setFiledata(Base64.getDecoder().decode(viewFiledata)); 39 keiyakuMasterRepository.save(keiyakuMaster); 40 return "redirect:/" + keiyakuMaster.getId(); 41 } 42 43 @GetMapping("/{id}") 44 public String result(@PathVariable Long id, Model model) { 45 var keiyakuMaster = keiyakuMasterRepository.findById(id).get(); 46 model.addAttribute("contentType", keiyakuMaster.getContentType()); 47 model.addAttribute("filedata", Base64.getEncoder().encodeToString(keiyakuMaster.getFiledata())); 48 return "result"; 49 } 50} 51 52

投稿2021/07/11 01:54

編集2021/07/11 09:04
KT001

総合スコア611

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

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

mimi_129

2021/07/11 05:14

回答ありがとうございます。 流れとしては、 1 editのinputでマルチパートで画像をcheckに渡す ↓ 2 checkでeditから受け取った画像を表示 ↓ 3 checkからfinishに画像を送りDBに保存となります。 いただいた回答ですと、 1から3への処理のみとなってしまいますので、checkでの確認画面が抜けてしまいます。。
KT001

2021/07/11 08:46

確認画面を追加してみました
mimi_129

2021/07/17 04:00 編集

いただいたコードを元に修正した所解決いたしました! ありがとうございました。 keiyakuMasterForm.setFiledata(Base64.getDecoder().decode(keiyakuMasterForm.getFiledataString())); byteをINSERTする際にデコードが抜けていたみたいです。 inputからfinishに渡った際にエンコードされた文字列をデコードする様に修正したら通りました。 ご丁寧にありがとうございました。 助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問