royB
royB

Reputation: 12977

Multipart request spring does not bind file data

I'm having a problem with a controller that i wrote in order to upload photos to a server.

the Controller

@RequestMapping(value = "photos", method = RequestMethod.POST)
@ResponseBody
public Response uploadPhoto(@RequestPart PhotoMetaData data, 
                            @RequestParam String localName,
                            @RequestPart(required = false) MultipartFile file, 
                            HttpServletRequest request) {

    log.info("@uploadPhoto > ip of request: " + request.getRemoteAddr() + ", metaData: " + data);

    return photosService.storePhoto(data, file, localName);
}

problem is that file is null but when inspecting request parameter the request clearly has 3 multipart params, each also has it's supposed contentType but file is a long string.

debug capturing

Android app is calling this code. i'm using OkHttp in order to build the multipart request. code:

MediaType jsonMediaType = MediaType.parse("application/json");
RequestBody requestBody = new MultipartBuilder()
             .type(MultipartBuilder.FORM)                                                                     
             .addPart(Headers.of("Content-Disposition", "form-data; name=\"data\""),                                         
              RequestBody.create(jsonMediaType, photoMetaDataStr))                                                                                                     
             .addPart(Headers.of("Content-Disposition", "form-data; name=\"localName\""),
              RequestBody.create(MediaType.parse("text/plain"), localName.getPath()))
             .addPart(Headers.of("Content-Disposition", "form-data; name=\"file\""),
              RequestBody.create(MediaType.parse("image/jpeg"), new File(localName.getPath())))
                                                    .build();

    Request request = new Request.Builder().url(url).post(requestBody).build();

    final Response response = client.newCall(request)
                                   .execute();

------ EDIT ------------

relevant beans:

@Bean
public MultipartResolver multipartResolver() {

    return new CommonsMultipartResolver();
}

---- EDIT 2 ----- after changing the controller signature such that file is required i'm getting an exception:

---- EDIT 3------ After extensive testing i've noticed that the problem is probably the way i'm using okHttp in order to send the multipart request to the server. using Postman client, the call was successful

error with request org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest@3d854606
org.springframework.web.multipart.support
.MissingServletRequestPartException: Required request part 'file' is not present.

Thanks for your time and help

Roy

Upvotes: 4

Views: 1985

Answers (1)

royB
royB

Reputation: 12977

Well i was able to solve the problem by just adding to the request the Content-Transfer-Encoding header.

RequestBody requestBody = new MultipartBuilder().type(MultipartBuilder.FORM)
                                                    .addPart(Headers.of("Content-Disposition", "form-data; name=\"data\""),
                                                            RequestBody.create(jsonMediaType, GsonInstance.getInstance()
                                                                                                          .toJson(photoMetaData)))
                                                    .addPart(Headers.of("Content-Disposition", "form-data; name=\"file\"; filename=\"localName\"", "Content-Transfer-Encoding", "binary"),
                                                            RequestBody.create(MediaType.parse("image/jpeg"), new File(localName.getPath())))
                                                    .build(); 

I'm not sure why it's matter. for my understanding the default transfer encoding is binary when the contentType is image. maybe it's a minor bug with okHttp?

Upvotes: 1

Related Questions