1. 序章

このチュートリアルでは、Spring Bootでマルチパートリクエストを送信するためのさまざまなメカニズムに焦点を当てます。 マルチパートリクエストは、単一のHTTPメソッド呼び出しの一部として、境界で区切られた多くの異なるタイプのデータを送信することで構成されます。

通常、複雑なJSON、XML、またはCSVデータを送信したり、このリクエストでマルチパートファイルを転送したりできます。 マルチパートファイルの例には、オーディオファイルや画像ファイルが含まれます。 さらに、マルチパートファイルを含む単純なキー/値ペアデータをマルチパートリクエストとして送信できます。

次に、このデータを送信するさまざまな方法を見てみましょう。

2. @ModelAttributeを使用する

フォームを使用して名前とファイルで構成される従業員のデータを送信する単純なユースケースを考えてみましょう。

まず、フォームデータを格納するためのEmployee抽象化を作成します。

public class Employee {
    private String name;
    private MultipartFile document;
}

次に、Thymeleafを使用してフォームを生成します。

<form action="#" th:action="@{/employee}" th:object="${employee}" method="post" enctype="multipart/form-data">
    <p>name: <input type="text" th:field="*{name}" /></p>
    <p>document:<input type="file" th:field="*{document}" multiple="multiple"/>
    <input type="submit" value="upload" />
    <input type="reset" value="Reset" /></p>
</form>

注意すべき重要な点は、ビューでenctypemultipart/form-dataとして宣言することです。

最後に、マルチパートファイルを含むフォームデータを受け入れるメソッドを作成します。

@RequestMapping(path = "/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public String saveEmployee(@ModelAttribute Employee employee) {
    employeeService.save(employee);
    return "employee/success";
}

ここで、2つの特に重要な詳細は次のとおりです。

  • consumes属性値がmultipart/form-dataに設定されています
  • @ModelAttributeは、アップロードされたファイルを含め、すべてのフォームデータ EmployeePOJOにキャプチャしました

3. @RequestPartを使用する

このアノテーションは、マルチパートリクエストの一部をメソッド引数に関連付けます。これは、JSONやXMLなどの複雑なマルチ属性データをペイロードとして送信する場合に役立ちます。

最初はEmployee型、2番目はMultipartFile型の2つの引数を持つメソッドを作成しましょう。 さらに、これらの引数の両方に@RequestPartで注釈を付けます。

@RequestMapping(path = "/requestpart/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public ResponseEntity<Object> saveEmployee(@RequestPart Employee employee, @RequestPart MultipartFile document) {
    employee.setDocument(document);
    employeeService.save(employee);
    return ResponseEntity.ok().build();
}

ここで、このアノテーションの動作を確認するために、MockMultipartFileを使用してテストを作成します。

@Test
public void givenEmployeeJsonAndMultipartFile_whenPostWithRequestPart_thenReturnsOK() throws Exception {
    MockMultipartFile employeeJson = new MockMultipartFile("employee", null,
      "application/json", "{\"name\": \"Emp Name\"}".getBytes());

    mockMvc.perform(multipart("/requestpart/employee")
      .file(A_FILE)
      .file(employeeJson))
      .andExpect(status().isOk());
}

上記で重要なことは、Employee部分のコンテンツタイプをapplication/JSONとして設定したことです。 このデータは、マルチパートファイルに加えてJSONファイルとしても送信されます。

マルチパートリクエストのテスト方法の詳細については、こちらをご覧ください。

4. @RequestParamを使用する

マルチパートデータを送信する別の方法は、@RequestParamを使用することです。 これは特にファイルと一緒にキー/値のペアとして送信される単純なデータに役立ちます。

@RequestMapping(path = "/requestparam/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public ResponseEntity<Object> saveEmployee(@RequestParam String name, @RequestPart MultipartFile document) {
    Employee employee = new Employee(name, document);
    employeeService.save(employee);
    return ResponseEntity.ok().build();
}

このメソッドのテストを書いて、次のことを示しましょう。

@Test
public void givenRequestPartAndRequestParam_whenPost_thenReturns200OK() throws Exception {
    mockMvc.perform(multipart("/requestparam/employee")
      .file(A_FILE)
      .param("name", "testname"))
      .andExpect(status().isOk());
}

5. 結論

この記事では、SpringBootでマルチパートリクエストを効果的に処理する方法を学びました。

最初に、モデル属性を使用してマルチパートフォームデータを送信しました。 次に、@RequestPartおよび@RequestParamアノテーションを使用してマルチパートデータを個別に受信する方法を確認しました。

いつものように、完全なソースコードはGitHubから入手できます。