やること
画像などのファイルとJSONにしたデータなどをaxios
を使って同時にPOSTし、Spring側ではオブジェクトへのマッピングとバリデーションをやります。
同じようなやり方で、Spring側でパースできるデータなら何でも同時に送ることができるはずです。
実行する
Java側
エンドポイントは以下の通りです。
@RequestPart
を使うのがキモです。
整数値とファイルとJSONのオブジェクトを受け取り、それぞれに関して出力を行います。
@PostMapping("/api/sample")
public void sample(
@RequestParam("intValue") Integer intValue,
@RequestPart("file") MultipartFile multipartFile,
@RequestPart("jsonValue") @Valid SampleObject sampleObject,
BindingResult bindingResult
) {
if(bindingResult.hasErrors()) {
//エラー処理
System.out.println(bindingResult.getAllErrors());
}
System.out.println(intValue);
System.out.println(multipartFile.getOriginalFilename());
System.out.println(sampleObject.getName());
}
受け取るオブジェクトは以下の通りです。
@Getter @Setter
public class SampleObject {
@NotBlank
private String name;
@NotNull
private String description;
}
JS側
POSTするコードは以下の通りです1。
new Blob
でtype : 'application/json'
を指定することがキモです。
送る内容についてはコメントを参照してください。
postSample (file) { //ファイルは引数で渡してもらう
const sampleObject = { //JSONにするオブジェクト
name: 'name',
description: null //descriptionをnullにすることでバリデーションに引っ掛ける
}
const formData = new FormData()
formData.append('file', file)
formData.append('jsonValue', new Blob([JSON.stringify(sampleObject)], {type : 'application/json'}))
formData.append('intValue', '1') //intValueは1を指定
axios.post('/api/sample', formData)
}
実行結果
送信したのは1.pngというファイルです。エラー含めちゃんと処理できていることが分かります。
[Field error in object 'jsonValue' on field 'description': rejected value [null]; codes [NotNull.jsonValue.description,NotNull.description,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [jsonValue.description,description]; arguments []; default message [description]]; default message [must not be null]]
1
1.png
name
失敗するコード
type : 'application/json
を指定しなければorg.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported requestpart
と怒られてしまいます。
application/octet-stream
というのは送信方法が指定されていないという意味で、ここにJSONを指定してやることでちゃんと動くようになります。
-
2スペースインデントセミコロンレススタイルです。 ↩