Spring文件上传未绑定到模型属性对象
问题内容:
我想使用Spring MVC构建一个简单的文件上传功能。
我已经安装了multipartResolver并且可以正常工作:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10240000"/>
</bean>
上载文件时,将记录以下内容:
DEBUG:[org.springframework.web.multipart.commons.CommonsMultipartResolver]: Found multipart file [imageUpload] of size 29081 bytes with original filename [xyz.jpg], stored at [/home/myuser/workspace/myProject/target/tmp/upload_67f1107c_1b8f_402c_bebd_6cd8a6e4c830_00000032.tmp]
告诉我它基本上在工作。
这是我的JSP的一部分:
<form:form modelAttribute="placeForm" action="/platz/save" method="post" cssClass="placeForm" enctype="multipart/form-data">
...
<label for="imageUpload">Upload</label>
<form:input type="file" path="imageUpload" id="imageUpload" accept="image/*" />
...
</form:form>
这是我的模型属性对象的类:
public class PlaceEditForm
{
@Valid
private Place place = new Place();
private Map<Integer, PlaceFeature> features;
private MultipartFile imageUpload;
... getter/setter omitted...
}
这是我的Controller方法的一部分:
@RequestMapping(value="/save", method=RequestMethod.POST)
public String savePlace (@Valid @ModelAttribute("placeForm") PlaceEditForm form, BindingResult result)
{
logger.debug("saveNewPlace");
logger.debug("Upload: "+form.getImageUpload()); // null
...
return "redirect:/platz/"+place.getPlaceId();
}
发生的是,没有填充表单对象的imageUpload属性(空),而所有其他表单属性都被填充。
我发现在控制器中使用它时它确实起作用:
@RequestMapping(value="/save", method=RequestMethod.POST)
public String savePlace (@Valid @ModelAttribute("placeForm") PlaceEditForm form, BindingResult result, @RequestParam("imageUpload") MultipartFile upload, BindingResult uploadResult)
{
logger.debug("saveNewPlace");
logger.debug("Upload: "+upload); // Works!!
...
return "redirect:/platz/"+place.getPlaceId();
}
因此,可以将MultipartFile用作@RequestParam
作品,但不能将其绑定到表单的modelAttribute
对象。我在网上发现了数百个相同的示例,但没有发现不同。
我仍在学习Spring,因此我可能会遗漏一个非常明显的观点。我可以只使用控制器的第二个版本,但我不理解它,正如我所说,我正在学习。
不应将中的所有<form:input path="abc">
属性<form:form modelAttribute="xyz">...</form:form>
都绑定到xyz.abc
吗?对于文件上传以外的所有属性,它的工作方式都是这样。
有什么见解吗?谢谢
问题答案:
我发现了问题:
我在控制器中有一个这样的方法,但是忘了添加imageUpload
属性。一旦发现非常愚蠢和容易..!
@InitBinder
public void initBinder(WebDataBinder binder)
{
binder.setAllowedFields("place.placeId", "place.name", "place.description", "place.directions", "place.coordinates*", "features*", "tmpFiles*", "removeFiles*");
}
这样可以防止绑定程序将除指定属性之外的任何其他属性绑定到modelAttribute。当您仅验证期望在前端的内容时,这是非常重要的安全措施,可防止犯罪者将危险信息输入系统。