Spring 测试:为数据文件发送多部分
Spring Tests: sending multipart for data file
在我们的 Spring 引导应用程序中,我们从这样的请求中获取一个多部分形式的数据文件:
ServletFileUpload upload = new ServletFileUpload();
try {
FileItemIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
FileItemStream item = iterStream.next();
if (item.getFieldName().equals("file")) {
return upload(
item.getName(),
item.getContentType(),
item.openStream()
);
}
}
现在我正在编写一个用于下载文件的集成测试。我使用 mockMvc
发送请求。我尝试了很多不同的选择:
File dataFile = resourceLoader.getResource("classpath:data/fakeload/test.pdf").getFile();
MockMultipartFile file = new MockMultipartFile("test", "test.pdf",MediaType.APPLICATION_PDF_VALUE, FileUtils.readFileToByteArray(dataFile));
mockMvc.perform(multipart("/api/project-others/documents")/*.file("test.pdf",FileUtils.readFileToByteArray(dataFile))*/.file(file)
.with(getAuthentication("AUTH"))
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE+";boundary=----WebKitFormBoundarylRihI4R4f6S5eHA2")
.requestAttr("file",FileUtils.readFileToByteArray(dataFile))
//.content(createFileContent(FileUtils.readFileToByteArray(dataFile),"WebKitFormBoundarylRihI4R4f6S5eHA2",MediaType.APPLICATION_PDF_VALUE,"test.pdf"))
.content(file.getBytes())
.param("projectId","1")
.param("docId","1")
)
.andExpect(status().isOk())
.andDo(print());
}
private byte[] createFileContent(byte[] data, String boundary, String contentType, String fileName){
String start = "--" + boundary + "\r\n Content-Disposition: form-data; name=\"file\"; filename=\""+fileName+"\"\r\n"
+ "Content-type: "+contentType+"\r\n\r\n";;
String end = "\r\n--" + boundary + "--"; // correction suggested @butfly
return ArrayUtils.addAll(start.getBytes(),ArrayUtils.addAll(data,end.getBytes()));
}
但是iterStream.hasNext()
总是false
(iterStream是空的)。我错过了什么?怎么了?
我想通了,我的错误是 boundary 的值
boundary=----WebKitFormBoundarylRihI4R4f6S5eHA2 - 错误
边界像 = q1w2e3r4t5y6u7i8o9 -right
正确的测试代码:
@Test
public void when_creating_document_expect_created_doc() throws Exception {
FileInputStream dataFile = new FileInputStream(resourceLoader.getResource("classpath:data/fakeload/test.pdf").getFile());
byte[] dataBytes = dataFile.readAllBytes();
postCreateDocument(USER_NAME, 1L, 1L, dataBytes)
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(3))
.andDo(print());
;
}
private ResultActions postCreateDocument(String username, Long projectOtherId, Long propertyId,
byte[] bytes) throws Exception {
String boundary = "q1w2e3r4t5y6u7i8o9";
var request = MockMvcRequestBuilders
.multipart("/api/project-others/documents")
.content(createFileContent(bytes, boundary, MediaType.APPLICATION_PDF_VALUE, "test.pdf"))
.param("projectOtherId", String.valueOf(projectOtherId))
.param("docTypeId", String.valueOf(propertyId))
.contentType("multipart/form-data; boundary=" + boundary)
.accept(MediaType.APPLICATION_JSON);
if (username != null) {
request.with(getAuthentication(username));
}
return mockMvc.perform(request);
}
public byte[] createFileContent(byte[] data, String boundary, String contentType, String fileName) {
String start = "--" + boundary + "\r\n Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n"
+ "Content-type: " + contentType + "\r\n\r\n";
String end = "\r\n--" + boundary + "--";
return ArrayUtils.addAll(start.getBytes(), ArrayUtils.addAll(data, end.getBytes()));
}
}
在我们的 Spring 引导应用程序中,我们从这样的请求中获取一个多部分形式的数据文件:
ServletFileUpload upload = new ServletFileUpload();
try {
FileItemIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
FileItemStream item = iterStream.next();
if (item.getFieldName().equals("file")) {
return upload(
item.getName(),
item.getContentType(),
item.openStream()
);
}
}
现在我正在编写一个用于下载文件的集成测试。我使用 mockMvc
发送请求。我尝试了很多不同的选择:
File dataFile = resourceLoader.getResource("classpath:data/fakeload/test.pdf").getFile();
MockMultipartFile file = new MockMultipartFile("test", "test.pdf",MediaType.APPLICATION_PDF_VALUE, FileUtils.readFileToByteArray(dataFile));
mockMvc.perform(multipart("/api/project-others/documents")/*.file("test.pdf",FileUtils.readFileToByteArray(dataFile))*/.file(file)
.with(getAuthentication("AUTH"))
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE+";boundary=----WebKitFormBoundarylRihI4R4f6S5eHA2")
.requestAttr("file",FileUtils.readFileToByteArray(dataFile))
//.content(createFileContent(FileUtils.readFileToByteArray(dataFile),"WebKitFormBoundarylRihI4R4f6S5eHA2",MediaType.APPLICATION_PDF_VALUE,"test.pdf"))
.content(file.getBytes())
.param("projectId","1")
.param("docId","1")
)
.andExpect(status().isOk())
.andDo(print());
}
private byte[] createFileContent(byte[] data, String boundary, String contentType, String fileName){
String start = "--" + boundary + "\r\n Content-Disposition: form-data; name=\"file\"; filename=\""+fileName+"\"\r\n"
+ "Content-type: "+contentType+"\r\n\r\n";;
String end = "\r\n--" + boundary + "--"; // correction suggested @butfly
return ArrayUtils.addAll(start.getBytes(),ArrayUtils.addAll(data,end.getBytes()));
}
但是iterStream.hasNext()
总是false
(iterStream是空的)。我错过了什么?怎么了?
我想通了,我的错误是 boundary 的值 boundary=----WebKitFormBoundarylRihI4R4f6S5eHA2 - 错误 边界像 = q1w2e3r4t5y6u7i8o9 -right
正确的测试代码:
@Test
public void when_creating_document_expect_created_doc() throws Exception {
FileInputStream dataFile = new FileInputStream(resourceLoader.getResource("classpath:data/fakeload/test.pdf").getFile());
byte[] dataBytes = dataFile.readAllBytes();
postCreateDocument(USER_NAME, 1L, 1L, dataBytes)
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(3))
.andDo(print());
;
}
private ResultActions postCreateDocument(String username, Long projectOtherId, Long propertyId,
byte[] bytes) throws Exception {
String boundary = "q1w2e3r4t5y6u7i8o9";
var request = MockMvcRequestBuilders
.multipart("/api/project-others/documents")
.content(createFileContent(bytes, boundary, MediaType.APPLICATION_PDF_VALUE, "test.pdf"))
.param("projectOtherId", String.valueOf(projectOtherId))
.param("docTypeId", String.valueOf(propertyId))
.contentType("multipart/form-data; boundary=" + boundary)
.accept(MediaType.APPLICATION_JSON);
if (username != null) {
request.with(getAuthentication(username));
}
return mockMvc.perform(request);
}
public byte[] createFileContent(byte[] data, String boundary, String contentType, String fileName) {
String start = "--" + boundary + "\r\n Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n"
+ "Content-type: " + contentType + "\r\n\r\n";
String end = "\r\n--" + boundary + "--";
return ArrayUtils.addAll(start.getBytes(), ArrayUtils.addAll(data, end.getBytes()));
}
}