基于SpringMVC的文件上传

在SpringBoot项目中,上传的文件默认不允许超过1M(也可能是其它值,根据SpringBoot的版本不同可能有差异),如果超出,将导致FileSizeLimitExceededException!如果需要自定义该限制值,需要在配置类中添加:

@Bean
public MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();

    factory.setMaxFileSize(DataSize.ofMegabytes(4));
    factory.setMaxRequestSize(DataSize.ofMegabytes(4));

    return factory.createMultipartConfig();
}
复制代码

注意:在开发项目时,在配置类中需要限制上传的文件大小,在控制器类中还要再次进行判断!因为,在同一个项目,可能有多种业务都涉及上传操作,例如“上传头像”、“上传商品图片”、“上传商品宣传视频”等,每种业务的限制值都应该不同,以上写在配置类中的限制值是全局化的限制值,也就是说“无论当前项目的哪个业务要上传文件,都不允许超过这个值”,所以,在配置类中的限制值一般是所有涉及上传的业务中的最大限制值,例如50MB,但是,如果每个业务都以50M为基准也是不合理,例如“上传头像”就应该限制为更小的值,则应该在控制器中再进行判断,所以,控制器中的方法都是针对不同的业务的,都应该独立的再次判断上传文件的大小!同时,还要注意,即使所有处理上传的控制器中都判断了文件大小,全局化的设置也应该是存在的,一方面是SpringBoot项目默认的限制值非常小(SpringMVC项目默认没有这个限制),另一方面是因为全局化的设置对应的验证会执行得更早,可以更早的将明显的错误拦截下来!

关于客户端,如果需要使用异步提交上传,基于jQuery的$.ajax()处理示例如下:

// 1. 将按钮的类型改为button,避免点击时按照传统方式提交表单
// 2. 为按钮添加id="btn-upload"
// 3. 为表单添加id="form-upload"
// 4. 表单中原有的action / method / enctype都已经不需要了,可以删除
// 5. 上传文件的ajax请求必须配置processData:false和contentType:false
$('#btn-upload').click(function () {
    $.ajax({
        url: '/upload',
        type: 'post',
        data: new FormData($('#form-upload')[0]),
        processData: false,
        contentType: false,
        success: function(result) {
            alert(result);
        }
    });
});
复制代码

如果需要一次性上传多个文件,首先,必须明确需要上传的多个文件的数量、定位,如果上传的多个文件是数量是固定的,且每个文件的定位是明确的(例如上传身份证照片的正面与反面),在设计客户端时,应该使用多个上传控件,例如:

<p>请身份证的正面照片:<input type="file" name="image1"></p>
<p>请身份证的反面照片:<input type="file" name="image2"></p>
复制代码

并且,在服务器端的控制器中,在处理请求的方法中,使用2个MultipartFile参数接收这2个文件,例如:

public String upload(MultipartFile image1, MultipartFile image2) {
    // 分别对image1和image2进行检查并上传
}
复制代码

另外,如果上传的多个文件的数量并不确定,但各文件的定位是相同的(例如发朋友圈),可以将上传控件设置为多选的,例如:

<p>请选择您要上传的文件(选择文件时按住Ctrl键即可选择多个文件):<input type="file" name="images" multiple="multiple"></p>
复制代码

或者,还可以利用JS技术动态添加上传控件,这些上传控件都是单选的,并且使用相同的name属性即可。

然后,在服务器端的控制器中,在处理请求的方法的参数列表中,使用MultipartFile[]类型接收这多个文件即可,例如:

public String upload(MultipartFile[] images) {
    // 遍历参数数组进行处理
}
复制代码