Spring Boot 控制器 - 将 Multipart 和 JSON 上传到 DTO [英] Spring Boot controller - Upload Multipart and JSON to DTO

查看:29
本文介绍了Spring Boot 控制器 - 将 Multipart 和 JSON 上传到 DTO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将表单内的文件上传到 Spring Boot API 端点.

I want to upload a file inside a form to a Spring Boot API endpoint.

UI 是用 React 编写的:

The UI is written in React:

export function createExpense(formData) {
  return dispatch => {
    axios.post(ENDPOINT,
      formData, 
      headers: {
        'Authorization': //...,
        'Content-Type': 'application/json'
      }
      ).then(({data}) => {
        //...
      })
      .catch(({response}) => {
        //...
      });
    };
}

  _onSubmit = values => {
    let formData = new FormData();
    formData.append('title', values.title);
    formData.append('description', values.description);
    formData.append('amount', values.amount);
    formData.append('image', values.image[0]);
    this.props.createExpense(formData);
  }

这是java端代码:

@RequestMapping(path = "/{groupId}", method = RequestMethod.POST)
public ExpenseSnippetGetDto create(@RequestBody ExpensePostDto expenseDto, @PathVariable long groupId, Principal principal, BindingResult result) throws IOException {
   //..
}

但是我在 Java 端遇到了这个异常:

But I get this exception on the Java side:

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundaryapHVvBsdZYc6j4Af;charset=UTF-8' not supported

我应该如何解决这个问题?类似的 API 端点和 JavaScript 端代码已经可用.

How should I resolve this issue? The similar API endpoints and JavaScript side code is already working.

我看过一个解决方案,它建议请求正文应该有 2 个属性:一个属于 JSON 部分,另一个用于图像.我想看看是否可以将它自动转换为 DTO.

I've seen a solution where it suggests that the request body should have 2 attributes: one which the JSON section goes under, another for the image. I'd like to see if it is possible to have it automatically converted to DTO.

客户端发送的上传payload应转换为如下DTO:

The upload payload sent by the client should be converted to the following DTO:

public class ExpensePostDto extends ExpenseBaseDto {

    private MultipartFile image;

    private String description;

    private List<Long> sharers;

}

所以你可以说它是 JSON 和 multipart 的混合体.

So you can say it's a mix of JSON and multipart.

问题的解决方法是前端使用FormData,后端使用ModelAttribute:

The solution to the problem is to use FormData on the front-end and ModelAttribute on the backend:

@RequestMapping(path = "/{groupId}", method = RequestMethod.POST,
        consumes = {"multipart/form-data"})
public ExpenseSnippetGetDto create(@ModelAttribute ExpensePostDto expenseDto, @PathVariable long groupId, Principal principal) throws IOException {
   //...
}

在前端,去掉Content-Type,因为它应该由浏览器本身决定,并使用FormData(标准JavaScript).那应该可以解决问题.

and on the front-end, get rid of Content-Type as it should be determined by the browser itself, and use FormData (standard JavaScript). That should solve the problem.

推荐答案

是的,您可以通过包装类来轻松完成.

Yes, you can simply do it via wrapper class.

1) 创建一个 Class 来保存表单数据:

1) Create a Class to hold form data:

public class FormWrapper {
    private MultipartFile image;
    private String title;
    private String description;
}

2) 创建一个 HTML form 用于提交数据:

2) Create an HTML form for submitting data:

<form method="POST" enctype="multipart/form-data" id="fileUploadForm" action="link">
    <input type="text" name="title"/><br/>
    <input type="text" name="description"/><br/><br/>
    <input type="file" name="image"/><br/><br/>
    <input type="submit" value="Submit" id="btnSubmit"/>
</form>

3) 创建一个方法来接收表单的text 数据和multipart 文件:

3) Create a method to receive form's text data and multipart file:

@PostMapping("/api/upload/multi/model")
public ResponseEntity<?> multiUploadFileModel(@ModelAttribute FormWrapper model) {
    try {
        // Save as you want as per requiremens
        saveUploadedFile(model.getImage());
        formRepo.save(mode.getTitle(), model.getDescription());
    } catch (IOException e) {
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    }

    return new ResponseEntity("Successfully uploaded!", HttpStatus.OK);
}

4) 保存file的方法:

private void saveUploadedFile(MultipartFile file) throws IOException {
    if (!file.isEmpty()) {
        byte[] bytes = file.getBytes();
        Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
        Files.write(path, bytes);
    }
}

这篇关于Spring Boot 控制器 - 将 Multipart 和 JSON 上传到 DTO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆