3

I wanted to build a simple Rest api using Spring boot which accepts any given file and then performs some operations on it . I went through the spring examples on multipartFile https://spring.io/guides/gs/uploading-files/ and I decided to follow the same approach. The files that will be uploaded through my rest api will have some specific extension. So,i gave the content-type as application/octet-stream . When I try to run my unit test cases for the same, I always get the exception of

nested exception is org.springframework.web.multipart.MultipartException: The current request is not a multipart request

This exception does not appear if the content type is text/plain or if there is no 'consumes' parameter in the requestMapping.

My controller code looks as follows :

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping("/v1/sample")
public class SampleController {

    private static Logger log = LoggerFactory.getLogger(SampleController.class);

    @RequestMapping(path = "/{id}/upload",
                    consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE},
                    method = RequestMethod.POST)
    public ResponseEntity<String> uploadfile(@PathVariable String id,
            @RequestParam("file") MultipartFile upgradeFile) {
        log.info("Obtained a upload request for the id {}",id );
        return new ResponseEntity<String>("file upload has been accepted.",
                HttpStatus.ACCEPTED);
    }

}

And my unit test snippet is as follows :

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import com.stellapps.devicemanager.fota.Application;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = Application.class)
@EnableWebMvc
public class ControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @Before
    public void mockMvcBuilder() {
        this.mockMvc = webAppContextSetup(webApplicationContext).build();
    }

    @Test
        public void test_ValidPayload() {
            String uri = "/v1/sample/1234/upload";
            Path path = Paths.get("src/test/resources/someFile");
            try {
                byte[] bytes = Files.readAllBytes(path);
                 MockMultipartFile multipartFile =
                            new MockMultipartFile("file", "someFile.diff", "application/octet-stream", bytes);
                 mockMvc.perform(fileUpload(uri).file(multipartFile).contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE))
                    .andExpect(status().isAccepted());
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
}

If I use text/plain as the content-type and i give a normal text file, it goes through fine. If I add the content-type as application/octet-stream it throws the following exception

    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.web.multipart.MultipartException: The current request is not a multipart request
    at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.assertIsMultipartRequest(RequestPartMethodArgumentResolver.java:204)
    at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.resolveArgument(RequestPartMethodArgumentResolver.java:129)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:99)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)

How Do I make my request accept application/octet-stream and what changes should I make to the test case to ensure it succeeds.

UPDATE:

Removing the consumes header and by not specifying the content-type in MockPartFile is one of the way to upload a file. I suppose by default the controller takes it as application/octet-stream

UPDATE:

Thank you for the response. I was using an earlier version of spring (1.3.1) and after going through the answer, I updated my spring version and the test case to match it and It started working.

2
  • Please provide a minimal reproducible example. How was your MockMvc set up? What does your multipart configuration look like? Commented Oct 26, 2016 at 15:43
  • Also, why are you expecting a bad request? Some things here don't check out, please edit your question with the details requested. Commented Oct 26, 2016 at 15:52

1 Answer 1

1

Try below steps

  • Remove the consumes from the RequestMapping attributes.
  • MockMultipartFile multipartFile = new MockMultipartFile("file","somename","multipart/form-data", fileinputstream);
  • Change to MockMvc:

    mockMvc.perform(MockMvcRequestBuilders.fileUpload("/v1/sample/1234/payload")                
                .file(multipartFile)
                .andExpect(status().isOk());
    

For help check Upload file using Spring mvc and MockMVC

EDIT:

I've tried a sample spring-boot-rest app with your scenario. Seems application/octet-stream is no issue. Please check my repo https://github.com/satya-j/boot-file-manager

Sign up to request clarification or add additional context in comments.

7 Comments

What difference will this make? What was wrong previously and how do these changes fix it?
My suggestion to the question is based on the file uploading mechanisms I have been using. All I can do is point at link [link]stackoverflow.com/a/33033540/7063373 . The scenario for most file uploading is submit through a form with some additional data , so multipart/form-data
If you think a post is a duplicate, flag to close it as such. Your answer currently inspires no confidence. You haven't given any explanation as to why their code/configuration/whatever doesn't work and haven't explained why your suggestions will make it work. It's a poor answer.
@SotiriosDelimanolis I agree, I'm new here. wasn't aware of flagging and haven't explored fully. Thanks for pointing it out. Would you suggest me to delete my answer ?
First, I would suggest you improve it if you can. See How do I write a good answer?. If you can't/don't know, then, sure, delete it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.