Search code examples
javaspringrestspring-mvcmultipart

Conversion between org.springframework.web.multipart.MultipartFile and org.springframework.core.io.Resource


I am trying to pass a resource as a @RequestPart to my controller.

@RequestPart(name = "resource", required = false) Resource multipartFile,

It seem to work good in my integration tests where I pass it as a Resource:

ByteArrayResource resource = new ByteArrayResource(new byte[] {65, 66, 67});    
MultipartBodyBuilder b = new  MultipartBodyBuilder();
b.part("resource", resource, MediaType.APPLICATION_PDF);
return webClient.post().uri(getUri()
                       .contentType(MediaType.MULTIPART_FORM_DATA)
                       .syncBody(b.build())
                       .retrieve()
                       .bodyToMono(Long.class);

However in unit tests, I always receive resource = null. I use MockMVC for that:

MvcResult result = mvc.perform(
            multipart(getUri())
                .file("resource", new byte[] {65, 66, 67})
                .content(new byte[] {65, 66, 67})
                .accept(MediaType.MULTIPART_FORM_DATA)
            .andExpect(status().isOk())
            .andReturn();

On the other hand, if I switch to using MultipartFile as parameter type in my Controller:

@RequestPart(name = "resource", required = false) MultipartFile multipartFile

It works if I pass a MockMultipartFile in unit tests, but I don't know how to pass a MultipartFile in my integration tests (and in the other service that uses my api). I tried implementing org.springframework.web.multipart.MultipartFile by wrapping over my ByteArrayResource, but it doesn't look right (and doesn't work). I've spent way too much time on this already... Any recommendations?

P.S. I use StandardServletMultipartResolver


Solution

  • I ended up with @RequestPart(name = "resource") Part part in controller, which works well with both

    ByteArrayResource resource = new ByteArrayResource(new byte[] {1, 2, 3});    
    MultipartBodyBuilder b = new MultipartBodyBuilder();
    b.part("resource", resource, MediaType.APPLICATION_PDF);
    return webClient.post().uri(getUri()
        .contentType(MediaType.MULTIPART_FORM_DATA)
        .syncBody(b.build())
        .retrieve()
        .bodyToMono(Long.class);
    

    and

    Part part = new MockPart("resource", new byte[]{1,2,3})
    MvcResult result = mvc.perform(multipart(getUri())
        .part(part)
        .andExpect(status().isOk())
        .andReturn();