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

查看:154
本文介绍了Spring启动控制器 - 将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。

Note 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.

更新1
客户端发送的上传有效负载应转换为以下DTO:

Update 1 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 (标准JS)。这应该可以解决问题。

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

推荐答案

是的,您可以通过包装类来完成。

Yes, you can simply do it via wrapper class.

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

1) Create a Class to hold form data

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

2)创建表格 for data

2) Create Form for 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)创建一个方法来接收表单的文本数据和 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 {
            saveUploadedFile(model.getImage());
            formRepo.save(mode.getTitle(),model.getDescription()); //Save as you want as per requirement 
        } catch (IOException e) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity("Successfully uploaded!", HttpStatus.OK);
    }

4)保存文件的方法

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启动控制器 - 将Multipart和JSON上传到DTO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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