From the previous blog it is pretty easy to guess how to do this, but here is the recipe as promised to upload images and store them on the file system. As the images are not stored in the database you can use MySQL for this as well.
Step 1: Add maven dependencies
Same as previous.
Step 2: Add properties to the ‘LogItem’
private String contentType;
private String path;
@Transient
private CommonsMultipartFile image;
Note here that the image is added as a CommonsMultipartFile, exactly as it is received by Spring, but it is marked @Transient which will prevent it from entering the database. Besides this a path is added to enable us to retrieve the image later.
Step 3: Update create.jspx to send a MultipartFile
Like in step 3 of the previous post, the form to create a LogItem is adjusted to our needs:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:spring="http://www.springframework.org/tags" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<jsp:output omit-xml-declaration="yes"/>
<form:create id="fc_raging_goblin_roo_domain_LogItem" modelAttribute="logItem" multipart="true" path="/logitems" render="${empty dependencies}" z="user-managed">
<field:input field="message" id="c_raging_goblin_roo_domain_LogItem_message" z="apnKidZldiFISmA4Q9pumki/o6Q="/>
<field:datetime dateTimePattern="${logItem_creationdate_date_format}" field="creationDate" id="c_raging_goblin_roo_domain_LogItem_creationDate" z="p5GCO6w9q76CIDoEn17xbZPqlT0="/>
<field:input field="image" id="c_raging_goblin_roo_domain_LogItem_image" type="file" z="user-managed"/>
<field:input field="contentType" id="c_raging_goblin_roo_domain_LogItem_contentType" render="false" z="user-managed"/>
<field:input field="path" id="c_raging_goblin_roo_domain_LogItem_path" z="P0zJQZkpJ19wRptpdaKLWSTr/BU=" render="false"/>
</form:create>
<form:dependency dependencies="${dependencies}" id="d_raging_goblin_roo_domain_LogItem" render="${not empty dependencies}" z="Qbb30wyy/eoxYyR+b/J66Ec1Lxw="/>
</div>
Edit 17-07-2013: See next post how to handle updates to an image.
Step 4: Update input.tagx to handle type=”file”
If you have not done so yet, adjust it as described in step 4 earlier.
Step 5: Add a method to the controller to send the actual image
Images are now loaded from the filesystem, to be precise from the path field:
@RequestMapping(value = "/{id}/image", method = RequestMethod.GET)
public String showImage(@PathVariable("id") Long id,
HttpServletResponse response, Model model) {
LogItem logItem = LogItem.findLogItem(id);
if (logItem != null && logItem.getPath() != null) {
try {
OutputStream out = response.getOutputStream();
response.setContentType(logItem.getContentType());
Files.copy(FileSystems.getDefault().getPath(logItem.getPath()),
out);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
Step 6: Change create and update methods of LogItemController to save image to the filesystem
The create and update methods now should store the image on the filesystem. With the new file-io of Java 7 this has never been easier.
@RequestMapping(method = RequestMethod.POST, produces = "text/html")
public String create(@Valid LogItem logItem, BindingResult bindingResult,
Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
populateEditForm(uiModel, logItem);
return "logitems/create";
}
uiModel.asMap().clear();
CommonsMultipartFile image = logItem.getImage();
if (image != null) {
File file = new File(image.getOriginalFilename());
try {
image.transferTo(file);
logItem.setContentType(image.getContentType());
logItem.setPath(file.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
return "logitems/create";
}
}
logItem.persist();
return "redirect:/logitems/"
+ encodeUrlPathSegment(logItem.getId().toString(),
httpServletRequest);
}
Note that the images will end up in the same directory where your webapp is running. This is something you probably wouldn’t do on a production system.
Step 7: Give webserver write access to the filesystem
Take care that the directory where you want to save the images is write-enabled for the webserver. Ok, I admit this is not really a decent step, but I just wanted to keep the numbering the same as in the previous post and this is the best I could come up with ;).
Step 8: Update show.jspx to display the image
The artificial step 7 allows me now to just redirect you to the previous step 8.