今天在做springboot环境下做一个文件上传的功能,刚开始测试小文件的时候,没有什么问题,但是一旦单个文件大小超过1M的时候,后台就会报
org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Unexpected EOF read on the socket
我的开发环境是:
1.springboot 2.0.3.RELEASE
2.java version "1.8.0_151"
刚开始遇到这个问题的时候,我也是一脸懵逼,因为根本找不到异常是从抛出来的,因为根本没有进入我们的controller层,在springboot的框架层就给我们拦下来了,并抛了出来。在网上看别人的解决方法,无非有两派,第一种:既然是tomcat内置的文件大小上传设置限制了单个文件上传的大小,那就通过修改tomcat配置文件来修改大小;第二种:是通过Bean配置来实现文件大小的修改。我测试了一下,其实两种方案都是在特定的环境下去解决的问题,恰巧我并不在这两种情景之中,但是通过分析,我们首先确认了是springboot框架层对文件大小做了基本限制,那我就尝试去修改这个值就可以了,这样我的问题就由这个exception转成了在springboot下去修改上传文件的大小。
而spring下也为我们提供了相关配置的设置,我们只需要去修改对应的值即可
spring
servlet:
multipart:
enabled: true
max-file-size: 10M #单个文件的最大上限
max-request-size: 30M #单个请求的文件总大小上限
哎,就是为了这个配置,我浪费了将近三个多小时。最后终于解决了,也学会了去转换思维。
后续跟踪:
在后来的测试中我发现即使我设置了大小之后,这个问题依然存在,并不是每次都会出现这个错误,而是处理时间稍微长一点的时候,这个错误就会出现。根据debug跟踪,我发现服务器在读取字节流的时候,读着读着突然IO流就中断了,最终把问题定位在了客户端,也就是说我服务器端在读取文件流的过程中,客户端主动关闭了连接。
首先看前端代码:
后端是form 采用post方式提交,在form的validate通过之后便直接开始提交,提交之后便关闭了当前的模态窗口。代码貌似没什么问题,其实问题就隐藏在这不起眼的地方,submit提交默认是异步了,我们本来的意愿是提交保存之后在关闭窗口和连接,而实际上当文件大一点的时候,异步提交相对耗时会稍微长一点,而这个时候我们主线程的close方法会将连接释放,从而导致我们客户端出现Socket的IO Exception. 改进方法 我们可以把后续的关闭操作放在submit的提交回调函数中处理
var options = {
//beforeSubmit: checkBefore,
success: handlerResult,
error: handlerError,
};
/**
* submit 提交成功结果处理
* */
function handlerResult(responseText) {
if(responseText.code == 0){
parent.location.reload();
$.modal.close();
$.modal.closeLoading();
}else{
$.modal.closeLoading();
alert(responseText.msg);
}
}
/**
* submit 提交失败结果处理
* */
function handlerError(responseText){
$.modal.closeLoading();
$.alertError(" 网络连接超时,保存失败!请稍后重试")
}
$("#form-softwareVersion-add").validate({
rules:{
brandId:{
required:true
},
typeId:{
required:true
},
softwareId:{
required:true
},
name:{
required:true
},
version:{
required:true
}
},
messages:{ //验证错误信息
brandId:{
required: '请输入品牌'
},
typeId:{
required: '请选择类型'
},
softwareId:{
required: '请选在更新类型'
},
name:{
required: '请输入版本名'
},
version:{
required: '请输入版本号'
}
},
submitHandler:function(form){
$.modal.loading("保存中");
$("#form-softwareVersion-add").ajaxSubmit(options);
}
});
到此问题真正解决,前端技术还欠火候。再次纪念下,加油!
千里之行,始于足下,读万卷书,不如行万里路!