【问题标题】:Content type 'multipart/form-data;boundary=----...;charset=UTF-8' not supported内容类型 'multipart/form-data;boundary=----...;charset=UTF-8' 不支持
【发布时间】:2018-06-11 13:56:51
【问题描述】:

我想向控制器发送一个对象,该对象具有多个文件列表和多个纯文本字段。

public class ContributionNew<T extends MovieInfoDTO> {
    private List<T> elementsToAdd;
    private Map<Long, T> elementsToUpdate;
    private Set<Long> idsToDelete;
    private Set<String> sources;
    private String comment;
}

public class Photo extends MovieInfoDTO {
    private MultipartFile photo;
}

@PostMapping(value = "/{id}/contributions/photos")
@ResponseStatus(HttpStatus.CREATED)
public
ResponseEntity<Void> createPhotoContribution(
        @ApiParam(value = "The movie ID", required = true)
        @PathVariable("id") final Long id,
        @ApiParam(value = "The contribution", required = true)
        @RequestBody @Valid final ContributionNew<Photo> contribution
) {

我正在使用postman 发送数据。然而,他把我扔了

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

我应该为这个控制器设置什么内容类型,以便我可以发送一个包含纯文本字段和文件列表的对象?

如果我在标题中设置标题

Content-type: multipart/form-data; charset=utf-8

它把我扔进控制台

org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found

【问题讨论】:

  • 不知道这是否重要,但multipart/form-data 不应该有charset。它确实需要boundary。见WWW Specification
  • 不过,更有可能是boundary 中的---- 引起了麻烦,因为-- 对边界标记有特殊含义。
  • @RequestBody 表示将 JSON 数据解析为 map 或 java bean,仅支持内容类型为 "application/json;charset=UTF-8"

标签: java spring rest spring-mvc spring-boot


【解决方案1】:

正如 dknight @RequestBody 所说,使用 JSON 或 XML 数据映射您的 DTO bean。 在 MultipartFile 的情况下,您不能使用 JSON 数据,因此您不能使用 @RequestBody。 尝试使用 @ModelAttribute 注释。

工作样本:

@PostMapping("/promoters")
@Timed
public ResponseEntity<PromoterDTO> createPromoter(@ModelAttribute PromoterDTO promoterDTO) throws URISyntaxException { ... }

像这样使用PromoterDTO:

    public class PromoterDTO implements Serializable {

        private Long id; 

        private String name;

        private String address;

        private MultipartFile logo;
    }

【讨论】:

  • 在实现这个之后,我的对象中得到了空值。所有字段均为空
  • 你设置了getter和setter吗?
  • 如果我在我的情况下使用@ModelAttribute,我知道它无法从字符串转换为我的子 DTO(我的主 DTO 中有其他 DTO)。我该如何解决?
【解决方案2】:

在 Postman 中,您需要将 body 设置为 raw 类型,然后从下拉列表中选择 JSON,我遇到了类似的问题,这解决了我的问题。

【讨论】:

  • 这是正确的答案;先生,您需要我们身边的更多爱!
  • 感谢您拯救了我的一天!
【解决方案3】:

不要使用@RequestBody,而是使用@RequestParam

【讨论】:

  • 您能否更详细地解释一下这将如何解决 OP 的问题?
  • 发送文件 content-type 应该是 multipart/form-data 所以 requestparam 接受 formdata 但对于请求正文 content-type 应该是 application/json 不处理文件。
【解决方案4】:

使用@ModelAttribute 而不是@ResponseBody,因为这会占用键值对中的数据,而后者用于像json 这样的对象。 在点击 api 时,只需传递对象的多部分类型和 json 键值对。效果很好!

stack overflow question on this

【讨论】:

    【解决方案5】:

    而不是@RequestBody,使用@ModelAttribute 之类的,

    @PostMapping(value = "/{id}/contributions/photos")
    @ResponseStatus(HttpStatus.CREATED)
    public
    ResponseEntity<Void> createPhotoContribution(
            @ApiParam(value = "The movie ID", required = true)
            @PathVariable("id") final Long id,
            @ApiParam(value = "The contribution", required = true)
            @ModelAttribute @Valid final ContributionNew<Photo> contribution
    ) {
    

    【讨论】:

      【解决方案6】:
      import org.springframework.web.bind.annotation.ModelAttribute;
      

      使用@ModelAttribute 而不是@RequestBody。它对我有用。

      【讨论】:

        【解决方案7】:

        produces = { "application/json" } 必须写在控制器中,而不是 consumes = { "application/json" }

        【讨论】:

          【解决方案8】:

          这是使用 Spring Boot 2.1.7 用 Kotlin 编写的完整代码示例

          示例使用ProfileRepository,这当然是你实现的东西。

          Kotlin 很好,因为 data class 已经实现了可序列化。

          请注意,模型对象属性必须使用var 而不是val,否则日志消息中的字段值将为空。

          import org.springframework.web.bind.annotation.ModelAttribute
          import org.springframework.web.bind.annotation.PostMapping
          import org.springframework.web.bind.annotation.RestController
          import org.springframework.web.multipart.MultipartFile
          
          @RestController
          class ExampleController(private val myProfileRepository: ProfileRepository) {
              
              @PostMapping("/api/uploadFile")
              fun createProvider(@ModelAttribute request: CreateProfileRequest): Provider {
                  println("received create request with photo: ${request.photo} for the following person ${request.name}")
                  return myProfileRepository.save(Provider(name = request.name!!))
              }
          }
          
          data class CreateProfileRequest(
              var name: String? = null,
              var photo: MultipartFile? = null
          )
          

          【讨论】:

            猜你喜欢
            • 2018-08-19
            • 1970-01-01
            • 2018-12-22
            • 1970-01-01
            • 1970-01-01
            • 2022-01-19
            • 2018-07-24
            • 2016-02-21
            • 2020-04-13
            相关资源
            最近更新 更多