如何在使用 Spring 和 Apache 文件上传时模拟分段文件上传

问题描述 投票:0回答:2

我正在进行的项目需要支持大文件上传并知道上传过程中所花费的时间。

为了处理大文件,我使用 Apache FileUpload 的流 API,这也使我能够测量保存完整流所花费的时间。

我遇到的问题是我似乎无法在此控制器上的集成测试中使用 MockMvc。我知道控制器可以正常工作,因为我已经使用邮递员成功上传了文件。

简化的控制器代码:

@PostMapping("/upload")
public String handleUpload(HttpServletRequest request) throws Exception {
    ServletFileUpload upload = new ServletFileUpload();
    FileItemIterator iterStream = upload.getItemIterator(request);
    while (iterStream.hasNext()) {
        FileItemStream item = iterStream.next();
        String name = item.getFieldName();
        InputStream stream = item.openStream();
        if (!item.isFormField()) {
            // Process the InputStream
        } else {
            String formFieldValue = Streams.asString(stream);
        }
    }
}

简化的测试代码:

private fun uploadFile(tfr: TestFileContainer) {
    val mockFile = MockMultipartFile("file", tfr.getData()) // .getData*() returns a ByteArray


    val receiveFileRequest = MockMvcRequestBuilders.multipart("/upload")
    .file(mockFile)
    .contentType(MediaType.MULTIPART_FORM_DATA)

    val result = mockMvc.perform(receiveFileRequest)
      .andExpect(status().isCreated)
      .andExpect(header().exists(LOCATION))
      .andReturn(

}

这是我目前遇到的错误

org.apache.tomcat.util.http.fileupload.FileUploadException: 请求被拒绝,因为未找到多部分边界

有人可以帮忙吗?

spring apache file upload mockmvc
2个回答
1
投票

MockMultipartFile
方法不起作用,因为 Spring 在幕后工作,只是传递文件。

最终使用

RestTemplate
来代替,因为它实际上构造了请求。


0
投票

您可以使用 org.apache.http.entity.mime.MultipartEntityBuilder 创建一个 HttpEntity,如下所示:

HttpEntity httpEntity = MultipartEntityBuilder.create()
        .addTextBody("text-form-field", "Just a line of text.")
        .addTextBody("object-form-field", objectMapper.writeValueAsString(workerMetrics), ContentType.APPLICATION_JSON)
        .addBinaryBody("binary-format", "This would not really be text".getBytes())
        .build();

Spring的MockMultipartHttpServletRequestBuilder的后处理,添加实体作为内容。复制实体的内容类型将为您设置边界。

mvc.perform(multipart("/upload")
        .with(request -> {
            try {
                request.setContent(httpEntity.getContent().readAllBytes());
                request.setContentType(httpEntity.getContentType().getValue());
                return request;
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        })
).andExpect(status().isAccepted());
© www.soinside.com 2019 - 2024. All rights reserved.