Spring Boot + Java でfileとStringデータを同時にform送信して処理する

File型とString型を一度にForm送信するやり方がわかったので備忘録として残しておきます。

##実現したいことのイメージ
こんな感じのフォームがあり、送信ボタンをクリックすると更新した情報にページが更新されてアラートが表示される

![スクリーンショット 2021-01-01 19.31.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637360/8e781aa8-f0a9-18c2-642c-d43de7f66607.png)
![スクリーンショット 2021-01-01 19.36.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637360/ca0d50a1-2cfd-56cc-95d9-98c1a06743ab.png)


```html
<form th:action="@{/portfolio/user/modify}" method="post" enctype="multipart/form-data">
          <table class="table table-hover table-bordered table-responsive-md text-center" th:object="${user}">
            <tr>
              <th scope="row" class="img-column">Profile Picture</th>
              <td style="position: relative;">
                <img th:src="${'data:image/png;base64,'+image}"
                  th:class="${user.getUserImg().length == 0 ? 'hidden' : 'mypage-img'}">
                <img src="/img/avator.png" alt="" th:class="${user.getUserImg().length == 0 ? 'mypage-img' : 'hidden'}">
                <label id="file-btn" for="userImg" class="bg-primary text-white">Choose your photo</label>
                <input type="file" name="file" id="userImg" style="display: none;">
                <p id="selected-status" class="mt-1">[Not yet selcted]</p>
              </td>
            </tr>
            <!-- Stringの<input>は省略 -->
            <button id="cancel-btn" class="btn btn-warning hidden" type="button">Cancel</button>
            <button id="submit-btn" class="btn btn-primary hidden" type="submit">Submit</button>
          </div>
        </form>
```

```java
// @Controller
@PostMapping(value = "/modify", consumes = { "multipart/form-data" }) // ポイント1: 「consumes = { "multipart/form-data" }」を追記
  public String modify(UserForm userForm, @RequestPart("file") MultipartFile file, Model m) { // ポイント2: 「@RequestPart」を追記 ※@RequestParamじゃない
    userService.update(userForm, file, loginSession.getUserId());
    User user = userService.findByUserId(loginSession.getUserId());
    userService.setLoginSession(user);
    m.addAttribute("user", user);
    Boolean completeMsg = true;
    m.addAttribute("completeMsg", completeMsg);
    return "mypage";
  }
```

```java
 // @Service
  public User findByUserNameAndPassword(String userName, String password) {
    return userRepos.findByUserNameAndPassword(userName, password);
  }
  // userテーブルに上書きする
  public int update(UserForm userForm, MultipartFile file, Integer userId) {
    String userName = userForm.getUserName();
    String familyName = userForm.getFamilyName();
    String firstName = userForm.getFirstName();
    String email = userForm.getEmail();
    String password = userForm.getPassword();
    String imgPath = "/img/user/" + file.getOriginalFilename();
    return userRepos.update(userName, familyName, firstName, email, password, imgPath, userId);
  }

```

```javascript
 /*修正完了ダイアログの初期化*/
      var dialog = bootbox.dialog({
        message: '<p class="text-center mb-0">Your profile picture has changed</p>',
        backdrop: true,
        centerVertical: true,
        show: false
      });

      /*ユーザ情報更新後のアラート表示*/
      const completeMsg = /*[[${completeMsg}]]*/ ''; // ポイント3: ユーザ情報更新処理の際にBooleanのインスタンスを作成してみるに渡しておいたものを利用してアラートを表示させる
      console.log("completeMsg : " + completeMsg);
      if (completeMsg) {
        dialog.modal('show');
      }

```