在做文件上传功能时,我们可能需要限制单次可上传文件的大小
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
<property name="maxUploadSize">
<!-- 上传文件大小限制为31M,31*1024*1024 -->
<value>32505856</value>
</property>
......
</bean>
当上传的文件大小超过限制,可以通过注解@ExceptionHandler( MaxUploadSizeExceededException.class) 进行捕获
/**
* 捕获上传文件过大异常
*/
@ExceptionHandler( MaxUploadSizeExceededException.class)
public void handleException( Exception ex){
// TODO Auto-generated method stub
}
然而事实上我们会发现一个问题:
这里设置文件上传最大限制为31M,那么上传一个1G大小的文件必然是没法通过的;但是这只在服务器接收页面传过来的数据超过了31M甚至是完整的1G之后才会抛出异常并被捕获。特别是在网速十分缓慢的时候,往往在文件上传了四五分钟之后才返回大小超出限制的提示,这就给用户带来了非常糟糕的操作体验。
毫无疑问,我们需要提前获取到上限阈值。通过翻看SpringMVC文件上传部分的源码,发现能够通过CommonsMultipartResolver 获取到设置的阈值。这里在进行文件上传操作时先获取限制值的大小,未超过大小才进行上传操作,虽然这多发起了一次请求,但带来了更好的操作体验。
@Autowired
private CommonsMultipartResolver cmr;
/**
* 获取文件设置信息
*/
@RequestMapping(value = "/getMaxSize")
@ResponseBody
public String getMaxSize( HttpServletRequest request) throws Exception {
JSONObject json = new JSONObject();
try{
FileUpload fu = cmr.getFileUpload();
long sizeMax = fu.getSizeMax(); // 最大文件大小限制
String encod = fu.getHeaderEncoding(); // 编码
json.put( "encod", encod);
json.put( "sizeMax", sizeMax);
json.put( "success", true);
}catch( Exception ne){
ne.printStackTrace();
json.put( "success", false);
}
return json.toJSONString();
}
实际中实现上传时,一般会使用 ajaxfileupload.js 通过创建 iframe 来达到异步上传的效果。所以我们需要修改 ajaxfileupload.js 文件的上传方法
ajaxFileUpload: function(s) {
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
s = jQuery.extend({}, jQuery.ajaxSettings, s);
/*
* 添加上传文件大小限制
* 当上传的文件大小超过限制值,不进行上传
* */
var fileObject = jQuery("#" + s.fileElementId);
if( !jQuery( fileObject).inSize()){
s.complete( {}, status = "error");
return;
}
......
inSize() 方法的定义
// 判断是否在最大限制之内
jQuery.prototype.inSize = function(){
var obj = this;
// 这里通过设定属性data-sizeMax来减少请求的次数
// 只有当属性data-sizeMax不存在时才发起请求获取文件大小的上限值
var sizeMax = obj.attr('data-sizeMax');
if( typeof( sizeMax) == 'undefined'){
jQuery.ajax({
url: $basePath + "/getMaxSize.jc",
type:"post",
dataType:"json",
async : false,
success:function( data){
sizeMax = data.sizeMax;
obj.attr( 'data-sizeMax', sizeMax);
}
});
}
if( typeof( sizeMax) != 'undefined' && sizeMax > 0){
var fileSize = obj[0].files[0].size;
if( typeof( fileSize) != 'undefined'){
// 比较上传文件的大小和上限值
if( fileSize > sizeMax){
var kb = sizeMax / 1024;
alert('文件大小不应大于' + kb + 'kb!');
return false;
}
}
}
return true;
}