I've created a photo uploader that works great using javax.ws.rs. Here's the signature and basic gist of it:
@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:
@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:
@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.
@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.
Follow this rules when creating a multipart form: Specify enctype="multipart/form-data" attribute on a form tag. Add a name attribute to a single input type="file" tag. DO NOT add a name attribute to any other input, select or textarea tags.
To pass the Json and Multipart in the POST method we need to mention our content type in the consume part. And we need to pass the given parameter as User and Multipart file. Here, make sure we can pass only String + file not POJO + file. Then convert the String to Json using ObjectMapper in Service layer.
FileInputStream inputFile = new FileInputStream( "path of the file"); MockMultipartFile file = new MockMultipartFile("file", "NameOfTheFile", "multipart/form-data", inputFile); now use the file input as multipart file.
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")
);
}
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.
@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());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With