Spring:JSON数据和文件在同一个请求中

我知道如何创建使用MediaType.MULTIPART_FORM_DATA@FormDataParam("file") FormDataBodyPart bodyPart处理文件的端点@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;
    }

目前,如果我在下面的邮递员请求的“原始”选项卡上添加一些JSON数据,我得到HTTP 415 Unsupported Media Type可能是因为我指定我使用MULTIPART_FORM_DATA但我也使用了@RequestBody ,它正在寻找JSON内容是APPLICATION_JSON 。 那么如何让JSON数据和一个文件在同一个请求中处理呢? 我知道在两个请求中可以做到这一点,如果可能,我只想在一个请求中做到这一点?

在这里输入图像描述


你为什么使用Spring和Jersey注释? 你应该坚持使用框架的注释。 既然你在使用泽西岛,应该坚持它的注释。

所以这里是关于你当前的代码和环境要考虑的事情。

  • 不能有两个独立的机构。 用你的代码,这就是你期望发生的事情。
  • 您可以将JSON作为多部分主体的一部分。 对于你也应该注释SomeModel与泽西@FormDataParam

    @POST
    @Path("somepath")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFileAndJSON(
             @FormDataParam("model") SomeModel someModel,
             @FormDataParam("file") FormDataBodyPart bodyPart) { 
    }
    
  • 在Jersey配置中,您需要确保注册MultiPartFeature 。 如果你不这样做,身体将不能被反序列化,并且你会得到异常和错误响应。

  • 现在邮差问题。 你可以在这里看到类似的问题。 问题在于未为JSON正文部分设置Content-Type 。 例如,身体可能看起来像

    --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中的预览按钮,您实际上可以看到身体。 问题是"model"部分没有Content-Type ,如"file"部分所示。 发生这种情况是因为您无法在邮递员中设置各个部分的Content-Type 。 你会看到的将从文件扩展名中被发现。 例如.txt文件将使邮递员将Content-Type设置为text/plain并将.png文件设置为image/png

    如果你看看上面的链接,我建议也许你可以使用.json文件而不是输入数据。 当然,那只是一个理论。 我没有真正测试它。

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

  • 不要在Postman中将Content-Type标题设置为multipart/form-data 。 它使用表单数据时为您设置。 我刚刚看到有人在设置标题时说有错误的帖子。 现在找不到帖子,也没有我确认的内容,但我只是将其忽略。


  • UPDATE

    因此,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);
    }
    

    是的,您可以将它作为多部分表单数据。

    你在angularjs中得到这样的结果:

    $scope.uploadFile = function () {
                    var file = $scope.selectedFile[0];
                    $scope.upload = $upload.upload({
                        url: 'api/upload',
                        method: 'POST',
                        data: angular.toJson($scope.model),
                        file: file
                    }).progress(function (evt) {
                        $scope.uploadProgress = parseInt(100.0 * evt.loaded / evt.total, 10);
                    }).success(function (data) {
                        //do something
                    });
                };
    
                $scope.onFileSelect = function ($files) {
                    $scope.uploadProgress = 0;
                    $scope.selectedFile = $files;
                };
    public Response uploadFileAndJSON(@RequestParam("data") String data,
                                          @MultiPartFile("file")File file) { 
      you can data as form data and convert it 
      like you want to your object using Gson jar.       
     return null;
        }
    

    看看它的angularjs代码:Angularjs如何上传多部分表单数据和文件?

    https://puspendu.wordpress.com/2012/08/23/restful-webservice-file-upload-with-jersey/

    链接地址: http://www.djcxy.com/p/48635.html

    上一篇: Spring: JSON data and file in the same request

    下一篇: Uploading both data and files in one form using Ajax?