javascript - Spring Boot Controller - 将 Multipart 和 JSON 上传到 DTO

标签 javascript java spring-boot

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

UI 是用 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 端遇到了这个异常:

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

我应该如何解决这个问题?类似的 API 端点和 JavaScript 端代码已经在运行。

注意

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

<小时/>

更新 1

客户端发送的上传负载应转换为以下 DTO:

public class ExpensePostDto extends ExpenseBaseDto {

    private MultipartFile image;

    private String description;

    private List<Long> sharers;

}

所以你可以说它是 JSON 和多部分的混合。

<小时/>

解决方案

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

@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)。这应该可以解决问题。

最佳答案

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

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

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

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

<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文件:

@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) 保存文件的方法:

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);
    }
}

关于javascript - Spring Boot Controller - 将 Multipart 和 JSON 上传到 DTO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49845355/

相关文章:

javascript - react-router-dom 中的重定向不会被调用

java - 如何对java密码程序进行多线程暴力破解

java - Spring session 登录

Spring boot-绑定(bind)属性【配置属性】

java - 如何处理 "feign.FeignException: [301 Moved Permanently] during [GET]"?

maven - Camel Spring Boot Maven到Gradle

javascript - 如何在php中将prompt()值存储到数据库中

javascript - 清除特定 div 及其子元素的所有页面样式

javascript - 将 UTC 时间添加到我的倒计时器

java - 反射 API 中的方法类