Java 如何使用 SpringMVC 和 MockMVC 为文件上传发布多部分/表单数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20389746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:36:23  来源:igfitidea点击:

How to Post multipart/form-data for a File Upload using SpringMVC and MockMVC

javarestspring-mvc

提问by Matt

I've created a photo uploader that works great using javax.ws.rs. Here's the signature and basic gist of it:

我创建了一个使用 javax.ws.rs 效果很好的照片上传器。这是它的签名和基本要点:

@POST
@Path("/upload/photo")
@Consumes("multipart/form-data")
@Produces("application/json")
public String uploadPhoto(InputStream stream){
        try {
            int read = 0;
            FileOutputStream fos = new FileOutputStream(file);
            CountingOutputStream out = new CountingOutputStream(fos);
            byte[] bytes = new byte[MAX_UPLOAD_SIZE];

            while ((read = stream.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
            out.flush();
            out.close();
        } catch (IOException e) {
            // TODO throw!
            e.printStackTrace();
        }
    //...
}

I can test this using apache.commons.httpClient library like this:

我可以像这样使用 apache.commons.httpClient 库来测试这个:

    @Test
    public void testUpload() {

        int statusCode = 0;
        String methodResult = null;

        String endpoint = SERVICE_HOST + "/upload/photo";

        PostMethod post = new PostMethod(endpoint);

        File file = new File("/home/me/Desktop/someFolder/image.jpg");

        FileRequestEntity entity = new FileRequestEntity(file, "multipart/form-data");

        post.setRequestEntity(entity);

        try {
            httpClient.executeMethod(post);
            methodResult = post.getResponseBodyAsString();
        } catch (HttpException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        statusCode = post.getStatusCode();

        post.releaseConnection();
            //...
    }

This works great! The problem is that the rest of the application is written using Spring MVC. When I use Spring Mock MVC testing framework the program just hangs (shown in the code snippet below this one). Here is the SpringMVC code for the uploader:

这很好用!问题是应用程序的其余部分是使用 Spring MVC 编写的。当我使用 Spring Mock MVC 测试框架时,程序只是挂起(显示在下面的代码片段中)。这是上传器的 SpringMVC 代码:

@ResponseBody
@RequestMapping(    produces="application/json",
                    consumes="multipart/form-data",
                    method=RequestMethod.POST,
                    value="/photo")
public String uploadPhoto(@RequestPart("file") MultipartFile multipartFile){

            try {
                int read = 0;
                FileOutputStream fos = new FileOutputStream(file);
                CountingOutputStream out = new CountingOutputStream(fos);
                byte[] bytes = new byte[MAX_UPLOAD_SIZE];

                while ((read = multipartFile.getInputStream().read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }

                out.flush();
                out.close();

            } catch (IOException e) {
                // TODO throw!
                e.printStackTrace();
            }
            //...
}

And below is what I've implemented for testing, using Spring Mock MVC. I think the problem has to do with using fileUpload(...). Is there a way to test using the normal post(..) instead, like I can with apache? I'd prefer to use an InputStream as the argument and avoid using a MultipartFile.

下面是我使用 Spring Mock MVC 实现的测试。我认为问题与使用 fileUpload(...) 有关。有没有办法使用普通的 post(..) 来测试,就像我可以用 apache 一样?我更喜欢使用 InputStream 作为参数并避免使用 MultipartFile。

@Test
public void testUpload() throws Exception {

    String endpoint = BASE_URL + "/upload/photo";

    FileInputStream fis = new FileInputStream("/home/me/Desktop/someFolder/image.jpg");
    MockMultipartFile multipartFile = new MockMultipartFile("file", fis);

    mockMvc.perform(fileUpload(endpoint)
            .file(multipartFile)
            .contentType(MediaType.MULTIPART_FORM_DATA))
            .andExpect(status().isOk());

}

Ideally, I'd like to use Spring MVC and the Spring Mock MVC framework, but the code I've provided just hangs on the while statement. Is what I'm doing correct as far as using the fileUpload method in the Spring test? Any advice is appreciated.

理想情况下,我想使用 Spring MVC 和 Spring Mock MVC 框架,但我提供的代码只是挂在 while 语句上。就在 Spring 测试中使用 fileUpload 方法而言,我所做的是否正确?任何建议表示赞赏。

采纳答案by Matt

  1. To add content to a mock post request use content(bytes[])
  2. media type parameter boundary was necessary
  1. 要将内容添加到模拟发布请求,请使用 content(bytes[])
  2. 媒体类型参数边界是必要的

Also, it was safe to use a plain old InputStream from java.io as a parameter for the upload method, and still use MockMultipartFile in the request.

此外,使用来自 java.io 的普通旧 InputStream 作为上传方法的参数是安全的,并且仍然在请求中使用 MockMultipartFile。

@Test
public void testUpload() throws Exception {

            String endpoint = BASE_URL + "/upload/photo";

            FileInputStream fis = new FileInputStream("/home/me/Desktop/someDir/image.jpg");
            MockMultipartFile multipartFile = new MockMultipartFile("file", fis);

            HashMap<String, String> contentTypeParams = new HashMap<String, String>();
            contentTypeParams.put("boundary", "265001916915724");
            MediaType mediaType = new MediaType("multipart", "form-data", contentTypeParams);

            mockMvc.perform(
                    post(endpoint)
                    .content(multipartFile.getBytes())
                    .contentType(mediaType))
                    .andExpect(status().isOk());
}

回答by hidehai

MockMvcRequestBuilders.fileUpload:

MockMvcRequestBuilders.fileUpload:

@Test
public void uploadTest() throws Exception {
    String endpoint = "/service/productsale/5/upload";
    FileInputStream fis = new FileInputStream("E:\test\test.jpg");
    MockMultipartFile multipartFile = new MockMultipartFile("file",fis);

    mockMvc.perform(MockMvcRequestBuilders.fileUpload(endpoint).file(multipartFile))
            .andExpect(MockMvcResultMatchers.model().attributeExists("imageVo"))
            .andDo(print())
            .andExpect(status().isOk());
}

回答by xiaofeig

By referring to the document, the code below can be more simple.

通过参考文档,下面的代码可以更简单。

@Test
public void testFileUpload() throws Exception {
    FileInputStream input = new FileInputStream("/Downloads/WX.png");
    MockMultipartFile file = new MockMultipartFile(
            "image",
            "[email protected]",
            "image/png",
            input);
    this.mockMvc
            .perform(
                multipart("/api/note/image/create")
                        .file(file)
                        .header("Authorization", "BearereyJhbGciOiJIUzUxMiJ9")
            );
}

回答by Alisha Raju

This link helped me: https://samerabdelkafi.wordpress.com/2014/08/03/spring-mvc-full-java-based-config/

这个链接对我有帮助:https: //samerabdelkafi.wordpress.com/2014/08/03/spring-mvc-full-java-based-config/

More specifically this configuration: @Override

更具体地说,此配置:@Override

public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}