java - Spring:同一请求中的JSON数据和文件

标签 java json spring rest multipartform-data

我知道如何使用 MediaType.MULTIPART_FORM_DATA@FormDataParam("file") FormDataBodyPart bodyPart 创建处理文件的端点,但我想知道我是否也可以该请求中有 JSON 数据吗?像这样的东西:

    @POST
    @Path("somepath")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFileAndJSON(@RequestBody SomeModel someModel,
                                      @FormDataParam("file") FormDataBodyPart bodyPart) { 
         return null;
    }

目前,如果我在以下 Postman 请求的“原始”选项卡上添加一些 JSON 数据,我会收到 HTTP 415 Unsupported Media Type 可能是因为我指定我使用 MULTIPART_FORM_DATA 但我也在使用 @RequestBody,它正在寻找 JSON 内容,即 APPLICATION_JSON。那么如何在同一请求中处理 JSON 数据和文件呢?我知道可以在两个请求中执行此操作,我只想在可能的情况下在一个请求中执行此操作?

enter image description here

最佳答案

为什么要同时使用 Spring 和 Jersey 注释?您应该坚持使用适用于框架的注释。由于您使用的是 Jersey,因此应坚持其 its 注释。

下面是您当前的代码和环境需要考虑的事项。

  1. 不能有两个独立的 body 。使用您的代码,这就是您期望发生的事情。
  2. 可以将 JSON 作为多部分正文的一部分。为此,您还应该使用 Jersey @FormDataParam

    注释 SomeModel
    @POST
    @Path("somepath")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFileAndJSON(
             @FormDataParam("model") SomeModel someModel,
             @FormDataParam("file") FormDataBodyPart bodyPart) { 
    }
    
  3. 在 Jersey 配置中,您需要确保注册 MultiPartFeature。如果不这样做,正文将无法反序列化,您将得到异常和错误响应。

  4. 现在是 Postman 问题。可以看到类似的问题here .问题是 Content-Type 没有为 JSON 正文部分设置。例如 body 可能看起来像

    --AaB03x
    Content-Disposition: form-data; name="model"
    
    {"some":"model", "data":"blah"}
    --AaB03x
    Content-Disposition: form-data; name="file"; filename="file1.txt"
    Content-Type: text/plain
    
    ... contents of file1.txt ...
    --AaB03x--
    

    如果您点击 Postman 中的 Preview 按钮,您实际上可以看到正文。问题是 "model" 部分没有 Content-Type,如您在 "file" 部分中所见。发生这种情况是因为您无法在 Postman 中设置各个部分的 Content-Type。您将看到的那个将从文件扩展名中发现。例如,.txt 文件将使 Postman 将 Content-Type 设置为 text/plain.png文件到 image/png

    如果您查看上面的链接,我建议您可以使用 .json 文件而不是键入数据。当然那只是一个理论。我实际上并没有测试它。

    在任何情况下,Content-Type 必须 被设置以便 Jersey 能够知道将其反序列化为 JSON。如果 .json 文件扩展理论没有成功,那么你可以使用不同的客户端,比如 cURL,我在链接中展示了一个例子,或者你可以使用 Jersey 客户端来测试,如所见here .

  5. 不要在 Postman 中将 Content-Type header 设置为 multipart/form-data。它会在您使用 form-data 时为您设置。我刚刚看到一个帖子,有人说你设置标题时有错误。现在找不到该帖子,也不是我已经确认的内容,但我会忽略它。


更新

因此 OP 能够找到一种方法将 Content-Type: application/json 设置为“模型”部分。但有时使用 Javascript 客户端时,您无法设置它。所以不会有Content-Type。如果是这种情况,Jersey 将无法反序列化 JSON,因为它不知道发送的实际上是 JSON。如果您绝对不能或不知道如何为各个部分设置 Content-Type,您可以求助于执行以下操作。

@POST
@Path("somepath")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileAndJSON(@FormDataParam("model") FormDataBodyPart jsonPart,
                                  @FormDataParam("file") FormDataBodyPart bodyPart) { 
     jsonPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
     SomeModel model = jsonPart.getValueAs(SomeModel.class);
}

关于java - Spring:同一请求中的JSON数据和文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33175113/

相关文章:

java - While 循环和黑屏

java - 如何获取添加到数据库的最后一个节点的值

json - 没有使用 json 编码为 go 语言中的结构获取正确的数据

python - 使用python替换json文件中的引号

java - 测试时似乎没有应用 spring-security 的配置

java - CamelContext 与 Spring

java - 在 Java 中对 XML 子树进行排序

java - Spring Batch 管理 UI - 覆盖文件上传位置

php - 从 API 响应访问 JSON 数据

java - Spring安全配置来验证LDAP用户