【问题标题】:Retrofit and Multipart Image Uploading with HTTP 400使用 HTTP 400 进行改造和多部分图像上传
【发布时间】:2015-09-16 05:49:49
【问题描述】:

我快哭了,因为我尝试了很多解决方案和主题,但都不起作用。

问题: 我必须将一个字符串(它是一个位图,但我有 base64 编码)上传到我们可爱的服务器,所以我在 Android 中创建了一个后台线程来执行此操作,并调用后端。我收到一条 HTTP 400 错误消息,其中包含以下消息:

org.springframework.web.bind.MissingServletRequestParameterException","message":"Required MultipartFile parameter 'file' is not present","path":"/backend/newimage"}.

我的标题:

Content-Disposition: form-data; name="file"
Content-Type: text/plain; charset=UTF-8
Content-Length: 24069
Content-Transfer-Encoding: binary
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA0JCgsK.......etc.....binary

我没有在标题中看到以下部分:

enctype:“multipart/form-data”)。 我不明白为什么,我的 retforit interce 看起来像这样:

@POST("/newimage")
@Multipart
String uploadImageToIdea(@Query("id") String id, @Part("file") String file );

我不明白错误信息,因为我这里有文件参数。

我尝试了以下方法(显然没有工作:

我调用后端的代码(不是最终版本,但首先让事情发挥作用:)):

   new Thread() {
                @Override
                public void run() {
                    MultipartTypedOutput file = new MultipartTypedOutput();
                    for (int i = 0; i < imagesToUpload.size(); ++i) {
                        Bitmap imageBitmap = imagesToUpload.get(i);
                        ByteArrayOutputStream stream = new ByteArrayOutputStream();

                        imageBitmap.compress(Bitmap.CompressFormat.JPEG, 60, stream);
                        byte[] byteArray = stream.toByteArray();
                        String bitmapString = Base64.encodeToString(byteArray, Base64.DEFAULT);
                        backend.uploadImageToIdea(submitIdeaResponse.getIdeaDetails().getId(), bitmapString);
                    }
                }
            }.start();

来自我的后端开发人员的说明:

您需要发送一个多部分请求 (enctype="multipart/form-data")。

那么,有人可以帮助我吗,为什么我有 HTTP 400 和上面的错误消息?我可以在我的代码中进行哪些更改以使此调用正常工作? 谢谢

【问题讨论】:

    标签: android file-upload retrofit bad-request


    【解决方案1】:

    您应该使用TypedFile 在 Multipart 中发送文件。

    @Multipart
    @POST("/newimage")
    String uploadImageToIdea(@Part("id") TypedString id, @Part("file") TypedFile file);
    

    更多信息link

    【讨论】:

    • 我已经尝试过这种方式,但明天我会重试。谢谢
    • HTTP 400,但我解决了,请看我上面的答案
    【解决方案2】:

    我有这个确切的问题有一段时间了。了解下面的工作代码应该可以帮助您解决这个问题。

    改造

    @Multipart @POST("/gifts")
    void save( @Part("gift") Gift gift,
               @Part("file") TypedFile file,
               Callback<Resource<Gift>> callback);
    

    春天

    @RequestMapping(value="/gifts", method=RequestMethod.POST)
    public @ResponseBody HttpEntity<Gift> addGift(
            @RequestPart Gift gift,
            @RequestPart MultipartFile file) {...}
    

    注意 Spring 将使用反射将部件名称与控制器方法参数匹配。所以参数 file 应该匹配部分“文件”。在 Spring 中,您始终可以通过手动添加部件名称来覆盖它:@RequestPart("file")

    调用示例:

    service.save(gift, typedFile, new Callback<Resource<Gift>>() {
    
            @Override
            public void success(Resource<Gift> resources, Response response)
            {/*...*/}
    
            @Override
            public void failure(RetrofitError error)
            {/* ... */}
    });
    

    提示;除非您想头疼,否则不要将多部分请求与查询字符串混合。从一个平台到另一个平台,零件与零件的匹配似乎效果很好。

    【讨论】:

    • 嘿 Xerosigma,所以如果 Note Spring 将使用反射将部件名称与控制器方法参数匹配,我m not good with TypedString ? Because there is no file param. I created my own TypedString with file param, but it didnt 工作。
    • 对。我认为你真正的问题是 TypedString 的整体使用。只需发送一个字符串部分,你应该会很好。
    【解决方案3】:

    好的,我已经找到解决办法了:

                         for (int i = 0; i < imagesToUpload.size(); ++i) {
                            Bitmap imageBitmap = imagesToUpload.get(i);
                            try {
                                String fileNameWithPath = getCacheDir().getAbsolutePath() + "file_" + String.valueOf(i);
                                FileOutputStream out = new FileOutputStream(fileNameWithPath);
                                imageBitmap.compress(Bitmap.CompressFormat.PNG, 60, out);
                                out.close();
                                backend.uploadImageToIdea(submitIdeaResponse.getIdeaDetails().getId(), new TypedFile("multipart/form-data",new File(fileNameWithPath)));
                            } catch (FileNotFoundException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
    

    改造界面如下:

        @POST("/newimage")
        @Multipart
        String uploadImageToIdea(@Part ("id") String id, @Part("file") TypedFile file );
    

    所以我不对图像进行 base64Code 编码并从内存上传,而是保存到缓存目录中并上传文件本身。使用 TypeFile 的 Retrofit。

    【讨论】:

    • 在哪里可以找到类 TypesFile?
    猜你喜欢
    • 2018-04-15
    • 2021-11-17
    • 2016-04-10
    • 2017-01-14
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多