I am trying to upload an image to a servlet, but every once and a while during automated testing, it silently fails.
Do you guys know what would cause this?
Here is the code on the server:
@ResponseBody
@RequestMapping(method = RequestMethod.POST)
public String upload(HttpServletRequest request) throws Exception {
BufferedImage image = null;
@SuppressWarnings("unchecked")
List<FileItem> items = new ServletFileUpload(
new DiskFileItemFactory()).parseRequest(request);
Logger.log(LogLevel.INFO, "Upload contains " + items.size()
+ " items.");
int i = 0;
for (FileItem item : items) {
Logger.log(LogLevel.INFO, "\tItem " + (i++) + ". Name:\t"
+ item.getName() + ", Type:\t" + item.getContentType());
// File is of type "file"
if (!item.isFormField()) {
InputStream inputStream = null;
try {
inputStream = item.getInputStream();
if (inputStream.available() == 0) {
Logger.log(LogLevel.WARN,
"Item shows file type, but no bytes are available");
}
image = ImageIO.read(inputStream);
if (image != null) {
break;
}
} catch (Exception e) {
Logger.log(LogLevel.ERROR,
"There was an error reading the image. "
+ ExceptionUtils.getFullStackTrace(e));
throw new Exception("image provided is not a valid image");
} finally {
if (inputStream != null) {
IOUtils.closeQuietly(inputStream);
}
}
}
}
if (image == null) {
Logger.log(LogLevel.ERROR, "Image was supposedly read correctly, but was null afterwards");
throw new Exception("Image provided could not be read");
}
//do stuff with image
...
}
Here is the test:
public void testImageUpload throws Exception {
HttpPost httppost = new HttpPost("path/to/endpoint");
File file=new File(imgLoc);
FileBody bin = new FileBody(file);
StringBody comment = new StringBody("Filename: " + file);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("upload-file", bin);
reqEntity.addPart("comment", comment);
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Connection","Keep-Alive");
httppost.setEntity(reqEntity);
HttpResponse response =testClient.getClient().execute(httppost);
imgResponse=response.getStatusLine().toString();
System.out.println(imgResponse);
BufferedReader reader = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
String line;
while ((line = reader.readLine()) != null){
output = output + " " +line;}
System.out.println("Image Response: "+output);
}
Here is the output from the server when it fails:
2013/10/02 05-53-32,287::LOG:INFO[com.example#upload:L130 -- Upload contains 2 items.]
2013/10/02 05-53-32,288::LOG:INFO[com.example#upload:L133 -- Item 0. Name: Dog.jpg, Type: application/octet-stream]
2013/10/02 05-53-32,288::LOG:WARN[com.example#upload:L140 -- Item shows file type, but no bytes are available]
2013/10/02 05-53-32,289::LOG:INFO[com.example#upload:L133 -- Item 1. Name: null, Type: text/plain; charset=ISO-8859-1]
2013/10/02 05-53-32,290::LOG:ERROR[com.example#upload:L159 -- Image was supposedly read correctly, but was null afterwards]
We catch the exception from the image upload and send back a response code of 422 back to the client, so on the test, we get imgResponse
==422 which is a failure case.
Note: this only happens sometimes you run the test.
Here is step by step configuration for file uploading by using Apache Commons FileUpload:
1. Add dependency jars for the following component. Here is the maven dependencies:
pom.xml
<dependencies>
<!-- Spring 3 MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<!-- Apache Commons file upload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<!-- Apache Commons IO -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<!-- JSTL for c: tag -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
If you are not using maven then download respective jar from the maven repository online.
2. Create a FileUploadForm model
FileUploadForm.java
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
public class FileUploadForm {
private List<MultipartFile> files;
//Getter and setter methods
}
3. Add resolver to MVC config file
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
4. Write FileUploadController
FileUploadController.java
@Controller
public class FileUploadController {
@RequestMapping(value = "/show", method = RequestMethod.GET)
public String displayForm() {
return "file_upload_form";
}
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(
@ModelAttribute("uploadForm") FileUploadForm uploadForm,
Model map) {
List<MultipartFile> files = uploadForm.getFiles();
List<String> fileNames = new ArrayList<String>();
if(null != files && files.size() > 0) {
for (MultipartFile multipartFile : files) {
String fileName = multipartFile.getOriginalFilename();
fileNames.add(fileName);
//Handle file content - multipartFile.getInputStream()
}
}
map.addAttribute("files", fileNames);
return "file_upload_success";
}
}
5. Write jsp views
file_upload_form.jsp
<html>
<head>
<title>Spring MVC Multiple File Upload</title>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script>
$(document).ready(function() {
//add more file components if Add is clicked
$('#addFile').click(function() {
var fileIndex = $('#fileTable tr').children().length - 1;
$('#fileTable').append(
'<tr><td>'+
' <input type="file" name="files['+ fileIndex +']" />'+
'</td></tr>');
});
});
</script>
</head>
<body>
<h1>Spring Multiple File Upload example</h1>
<form method="post" action="save.html"
**enctype="multipart/form-data"**>
<p>Select files to upload. Press Add button to add more file inputs.</p>
<input id="addFile" type="button" value="Add File" />
<table id="fileTable">
<tr>
<td><input name="files[0]" type="file" /></td>
</tr>
<tr>
<td><input name="files[1]" type="file" /></td>
</tr>
</table>
<br/><input type="submit" value="Upload" />
</form>
</body>
</html>
Reference: http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/mvc.html#mvc-multipart
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