Retrofit and Multipart Image Uploading with HTTP 400

假装没事ソ 提交于 2019-12-11 03:18:45

问题


Im about to start crying, because Ive tried many solutions and topics, but it doesn`t work.

The issue: I have to upload an String (it was a bitmap, but I have base64 coded) to our lovely server, so I have created a background Thread in Android to do it, and calling the backend. I get a HTTP 400 error message, with the following message:

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

My headers:

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

I don`t see in headers the following part:

enctype: "multipart/form-data”). and I don`t understand why, my retforit interce looks like this:

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

I don`t understand the error message, because I HAVE the file param here.

I had tried the following (didn`t work obviously:

  • Retrofit Multipart Upload Image failed
  • Retrofit - @Body parameters cannot be used with form or multi-part encoding (added @Headers, in this case I had more header before my request, but didn`t changed anything.)

my code to call the backend (not the final version, but first let things make work :) ):

   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();

Note from my backend developer:

You need to send a multipart request (enctype="multipart/form-data”).

So, can someone please help me out, why I have HTTP 400 with the error message above? What can I change in my code to make this call work ? Thank you


回答1:


You should use TypedFile for sending file in Multipart.

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

for more information link.




回答2:


I had this exact issue for some time. Understanding the working code below should help you resolve this.

Retrofit

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

Spring

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

Note Spring will use reflection to match part names with controller method parameters. So the parameter file should match part "file". You can always override this in Spring by adding the part name manually: @RequestPart("file")

Example Call:

service.save(gift, typedFile, new Callback<Resource<Gift>>() {

        @Override
        public void success(Resource<Gift> resources, Response response)
        {/*...*/}

        @Override
        public void failure(RetrofitError error)
        {/* ... */}
});

Tip; don't mix multipart request with query strings unless you want a headache. Matching parts with parts seems to work well from one platform to another.




回答3:


Okay, I have figured out the solution:

                     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();
                        }

and the retrofit interface is the following:

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

So I don`t base64Code the image and uploading from the memory, BUT saving into the cache dir and upload the file itself. Using TypeFile of Retrofit for it.



来源:https://stackoverflow.com/questions/31121212/retrofit-and-multipart-image-uploading-with-http-400

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!