【问题标题】:Can I mix media types in a Spring Rest method?我可以在 Spring Rest 方法中混合媒体类型吗?
【发布时间】:2014-12-11 00:42:05
【问题描述】:

我目前正在尝试编写一个接受文件上传的 ReST 方法。当用户提交文件时,我还希望他们添加描述,以及与文件内容有关的其他一些元数据(例如,与文件内容关联的“类型”)。我正在使用 Spring 4 的 Spring MVC 控制器。

这是我想做的一个例子:

@RequestMapping(value = "/file", method = RequestMethod.POST)
public @ResponseBody
ResponseEntity<MyFileDTO> uploadCustomAnnotationFile(
        @RequestParam("file") MultipartFile uploadFile,
        @RequestBody MyFileDetailsDTO fileDetails) {
    log.debug("This is working!");
}

但是,如果我尝试通过 Swagger UI 调用此方法,则会收到不受支持的媒体类型异常:

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundarycAbgNBTQ09GQTBif' not supported

我怀疑我不能在 1 个请求中混合 application/json 和 multipart/form-data?

更新: 根据 zeroflagL 的回复并遵循提供的指向特定于我正在尝试做的文档的链接,并使用@RequestPart 而不是@RequestBody,我取得了少量进展,但这仍然不起作用。

新方法签名:

@RequestMapping(value = "/file", method = RequestMethod.POST)
public @ResponseBody
ResponseEntity<MyFileDTO> uploadCustomAnnotationFile(
        @RequestPart MultipartFile uploadFile,
        @RequestPart MyFileDetailsDTO fileDetails) {
    log.debug("This is working!");
}

新异常:

2014-12-11 09:21:45.237 [http-nio-8443-exec-8] ERROR c.i.h.c.ControllerExceptionHandler   [ControllerExceptionHandler.groovy:58] - Controller Exception
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'fileDetails' is not present.

提前致谢, 托尼亚

【问题讨论】:

  • 请注意,如果您的@Controller 类在其@RequestMappingconsumes 属性中声明了错误的端点格式,也可能会抛出HttpMediaTypeNotSupportedException,例如,如果您在类中声明consumes={"application/json"}级别,但随后有一个需要使用“multipart/form-data”的端点。

标签: java spring rest spring-mvc


【解决方案1】:

您可以在 Spring REST 方法中混合媒体类型。 @zeroflagL/ 答案可能是对的。但@RequestPart 工作正常。这是我的代码,和你的没什么不同

@RequestMapping(value = "/interface/member/v1/register.do", method = RequestMethod.POST)
@ResponseBody
public RegisterResponse register(@RequestPart(value = "registerRequest") RegisterRequest registerRequest,
@RequestPart(value = "attachment", required = false) MultipartFile file) throws ServiceException {
    return memberV1Service.register(registerRequest, file);
}

我建议,您应该检查您的请求。不是您的服务器端代码。 这是我的测试预览代码(我在 Chrome 中使用 Postman 进行了测试)

    POST /was/interface/member/v1/register.do HTTP/1.1
    Host: localhost:8080
    Cache-Control: no-cache

    ----WebKitFormBoundaryE19zNvXGzXaLvS5C
    Content-Disposition: form-data; name="registerRequest"

    { -- some of my json format content}
    ----WebKitFormBoundaryE19zNvXGzXaLvS5C
    Content-Disposition: form-data; name="attachment"; filename="IMG_0089.JPG"
    Content-Type: image/jpeg


    ----WebKitFormBoundaryE19zNvXGzXaLvS5C

请求中缺少 Content-Type。此测试因 MissingServletRequestPartException 而失败,原因是所需的请求部分“registerRequest”不存在。

您可以使用 RESTClient 或其他方式进行测试,并检查 Content-Type 是否存在。

【讨论】:

    【解决方案2】:

    Spring documentation 明确说明了要做什么。

    混合 application/json 和 multipart/form-data 的想法是错误的,因为 application/json 将是 multipart(原文如此!)请求的一部分。

    WebKitFormBoundary 让我认为您尝试从浏览器发送 AJAX 请求,我想知道您是否真的发送 JSON。 AFAIK 不可能像 Spring 文档中显示的那样显式添加(真实)JSON 部分。也许您可以向我们展示客户端代码。

    无论如何你不能使用@RequestBody,因为那会包含你要上传的文件。您必须使用@RequestPart。如果您在文件旁边发送表单数据(而不是 JSON),那么您根本不需要任何注释。

    【讨论】:

    • 还没有客户端代码。正如我在原帖中所说,我正在使用 Swagger UI 来测试我的 ReST 端点。我使用 Swing 注释已经有一段时间了,@RequestBody 是我配置我的 ReST 端点以接受/期望请求“正文”中的 JSON 数据的方式。即使它与查询参数和/或路径参数结合使用,我也从未遇到过使用 @RequestBody 的问题。但是,与 MultipartFile 结合使用...现在是一个问题。该方法不需要该参数的 JSON 数据,并抛出无效媒体类型的异常。
    • @TonyaOhrel Swagger UI 在浏览器中运行,因此如果您的最终客户端不在浏览器中运行,它会有所不同。在这种情况下,您也根本不需要任何注释。
    猜你喜欢
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 2021-12-21
    相关资源
    最近更新 更多