无法使用 Spring MVC 将大文件上传到服务器?
Could not upload large file to server by using Spring MVC?
我已阅读文章 "File upload using Spring MVC and annotation configuration"
(http://www.raistudies.com/spring/spring-mvc/file-upload-spring-mvc-annotation)
我真的从中学到了一些有用的东西,感谢这篇文章!
当我上传一个小文件时,它在 Tomcat-8.0.20 中工作正常。
但是,当我上传一个大于 3M 字节的大文件时,MaxUploadSizeExceededException 会被捕获 "twice" ,然后 浏览器和服务器之间的连接就会中断。浏览器报告 ERR_CONNECTION_RESET 错误,但没有显示错误信息(或页面),看起来像是有人拔掉了我电脑的电缆。
我的系统环境是:
JRE1.8+Tomcat-8.0.20+WAR_package
我的 tomcat 是一个全新的干净 tomcat 在一个新文件夹中,其中只有这个 WAR。
我用Spring 4.1.4试过了,问题依旧。
顺便说一句,文件上传的惰性模式不适合我的情况。所以我需要在捕获到 MaxUploadSizeExceededException 时立即向用户报告结果。
这就是我所期望的。
如何解决上传大文件导致的这个"disconnection"问题?
非常感谢和最诚挚的问候!
@Controller
@RequestMapping(value="/FileUploadForm.htm")
public class UploadFormController implements HandlerExceptionResolver
{//this is the Exception Handler and Controller class
@RequestMapping(method=RequestMethod.GET)
public String showForm(ModelMap model){
UploadForm form = new UploadForm();
model.addAttribute("FORM", form);
return "FileUploadForm";
}
@RequestMapping(method=RequestMethod.POST)
public String processForm(@ModelAttribute(value="FORM") UploadForm form,BindingResult result){
if(!result.hasErrors()){
FileOutputStream outputStream = null;
String filePath = System.getProperty("java.io.tmpdir") + "/" + form.getFile().getOriginalFilename();
try {
outputStream = new FileOutputStream(new File(filePath));
outputStream.write(form.getFile().getFileItem().get());
outputStream.close();
} catch (Exception e) {
System.out.println("Error while saving file");
return "FileUploadForm";
}
return "success";
}else{
return "FileUploadForm";
}
}
//MaxUploadSizeExceededException can be catched here.....but twice..
//then some weird happend, the connection between browser and server is broken...
@Override
public ModelAndView resolveException(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception exception) {
Map<Object, Object> model = new HashMap<Object, Object>();
if (exception instanceof MaxUploadSizeExceededException){
model.put("errors", "File size should be less then "+
((MaxUploadSizeExceededException)exception).getMaxUploadSize()+" byte.");
} else{
model.put("errors", "Unexpected error: " + exception.getMessage());
}
model.put("FORM", new UploadForm());
return new ModelAndView("/FileUploadForm", (Map) model);//the programme can run to this line and return a ModelAndView object normally
}
}
更改 CommonsMultipartResolver
配置以使用更大的上传大小。例如,以下行会将最大上传大小设置为 100MB。
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000000"/>
</bean>
如果您在浏览器和 Tomcat 之间使用网络服务器,请务必同时更改网络服务器上的上传大小和连接超时,否则请求可能会在到达 [=16= 之前超时].
我已经确认我遇到的问题是 Tomcat7/8 中止上传请求的机制。一个新的属性 "maxSwallowSize" 是处理这种情况的关键。当您上传大于 2M 的文件时应该会发生这种情况。
因为2M是这个新属性的默认值。 Tomcat7/8 无法吞下从浏览器上传的剩余文件字节,所以它只是断开连接。请访问 http://tomcat.apache.org/tomcat-8.0-doc/config/http.html 并搜索 "maxSwallowSize"。
我已阅读文章 "File upload using Spring MVC and annotation configuration" (http://www.raistudies.com/spring/spring-mvc/file-upload-spring-mvc-annotation)
我真的从中学到了一些有用的东西,感谢这篇文章!
当我上传一个小文件时,它在 Tomcat-8.0.20 中工作正常。
但是,当我上传一个大于 3M 字节的大文件时,MaxUploadSizeExceededException 会被捕获 "twice" ,然后 浏览器和服务器之间的连接就会中断。浏览器报告 ERR_CONNECTION_RESET 错误,但没有显示错误信息(或页面),看起来像是有人拔掉了我电脑的电缆。
我的系统环境是: JRE1.8+Tomcat-8.0.20+WAR_package 我的 tomcat 是一个全新的干净 tomcat 在一个新文件夹中,其中只有这个 WAR。
我用Spring 4.1.4试过了,问题依旧。
顺便说一句,文件上传的惰性模式不适合我的情况。所以我需要在捕获到 MaxUploadSizeExceededException 时立即向用户报告结果。 这就是我所期望的。
如何解决上传大文件导致的这个"disconnection"问题?
非常感谢和最诚挚的问候!
@Controller
@RequestMapping(value="/FileUploadForm.htm")
public class UploadFormController implements HandlerExceptionResolver
{//this is the Exception Handler and Controller class
@RequestMapping(method=RequestMethod.GET)
public String showForm(ModelMap model){
UploadForm form = new UploadForm();
model.addAttribute("FORM", form);
return "FileUploadForm";
}
@RequestMapping(method=RequestMethod.POST)
public String processForm(@ModelAttribute(value="FORM") UploadForm form,BindingResult result){
if(!result.hasErrors()){
FileOutputStream outputStream = null;
String filePath = System.getProperty("java.io.tmpdir") + "/" + form.getFile().getOriginalFilename();
try {
outputStream = new FileOutputStream(new File(filePath));
outputStream.write(form.getFile().getFileItem().get());
outputStream.close();
} catch (Exception e) {
System.out.println("Error while saving file");
return "FileUploadForm";
}
return "success";
}else{
return "FileUploadForm";
}
}
//MaxUploadSizeExceededException can be catched here.....but twice..
//then some weird happend, the connection between browser and server is broken...
@Override
public ModelAndView resolveException(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception exception) {
Map<Object, Object> model = new HashMap<Object, Object>();
if (exception instanceof MaxUploadSizeExceededException){
model.put("errors", "File size should be less then "+
((MaxUploadSizeExceededException)exception).getMaxUploadSize()+" byte.");
} else{
model.put("errors", "Unexpected error: " + exception.getMessage());
}
model.put("FORM", new UploadForm());
return new ModelAndView("/FileUploadForm", (Map) model);//the programme can run to this line and return a ModelAndView object normally
}
}
更改 CommonsMultipartResolver
配置以使用更大的上传大小。例如,以下行会将最大上传大小设置为 100MB。
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000000"/>
</bean>
如果您在浏览器和 Tomcat 之间使用网络服务器,请务必同时更改网络服务器上的上传大小和连接超时,否则请求可能会在到达 [=16= 之前超时].
我已经确认我遇到的问题是 Tomcat7/8 中止上传请求的机制。一个新的属性 "maxSwallowSize" 是处理这种情况的关键。当您上传大于 2M 的文件时应该会发生这种情况。
因为2M是这个新属性的默认值。 Tomcat7/8 无法吞下从浏览器上传的剩余文件字节,所以它只是断开连接。请访问 http://tomcat.apache.org/tomcat-8.0-doc/config/http.html 并搜索 "maxSwallowSize"。