1:前端页面
<form action="/upload" method="post" enctype="multipart/form-data">
<p>请选择您要上传的文件</p>
<p><input type="file" name="file"/></p>
<p><input type="submit" value="提交" /></p>
</form>
注意:以上代码中,表单的提交方式必须是POST,表单必须配置enctype=“multipart/form-data”!
2:后端 在控制器中处理请求的方法的参数列表中添加@RequestParam(“file”) MultipartFile file参数:
@RequestParam("")注解里的参数和前端页面,<input>里的name属性一致
@RequestMapping("/upload")
public String handleUpload(
@RequestParam("file") MultipartFile file) {
System.out.println("UploadController.handleUpload()");
return null;
}
3:一次上传多个文件
如果上传的文件数量是固定的,可以在页面中添加多个<input type=“file” />,为每个控件设置不同的name属性,然后,在控制器中,使用多个MultipartFile参数来处理!
如果上传的文件数量是不固定的,可以在使用<input type=“file” />控件时,为该控件添加multiple=“multiple”,在选择文件时,就可以按住Ctrl键同时选中多个文件,在控制器,将参数声明为MultipartFile[] file,即声明为数组格式,然后遍历该数组进行处理!
4: 关于MultipartFile的API
boolean isEmpty():判断上传的文件是否为空,如果客户端上传的表单中没有选择文件就直接上传,或上传的文件是0字节的,即为空;
String getOriginalFilename():获取文件的原始文件名,即该文件在客户端设备中的文件名;
long getSize():获取上传的文件的大小,以字节为单位;
String getContentType():获取文件的MIME类型,通常用于限制上传的文件的类型;
InputStream getInputStream():获取上传的文件的输入流,通常用于自定义读取文件数据的过程,例如配置读取时使用的缓冲区等,该方法与transferTo()方法不可以同时使用;
void transferTo(File dest):保存客户端上传的文件,如果是较小的文件,调用该方法会比较方便,如果是较大的文件,推荐使用getInputStream()获取输入流后自定义处理过程,该方法与getInputStream()方法不可以同时使用。
5:限制文件大小
在SpringBoot项目中,上传文件时,默认配置了MultipartResolver的上传文件大小,限制为最大1MB!如果需要自定义配置值,则需要在启动类xxxApplication中添加:
@Bean
public MultipartConfigElement getMultipartConfigElement() {
MultipartConfigFactory factory
= new MultipartConfigFactory();
DataSize maxSize = DataSize.ofMegabytes(50);
factory.setMaxFileSize(maxSize);
factory.setMaxRequestSize(maxSize);
return factory.createMultipartConfig();
}
然后,在启动类xxxApplication的声明之前添加@Configration注解即可。
除了以上做法以外,还可以通过在application.properties中添加配置,来设置上传文件大小的上限值:
spring.servlet.multipart.max-file-size=???
spring.servlet.multipart.max-request-size=???
需要注意的是,在SpringBoot框架的历史版本更新中,以上配置代码经过几次调整,以上代码只适用于SpringBoot 2.x版本,如果是SpringBoot 1.3.x或更低版本,配置的名称应该是:
multipart.maxFileSize
multipart.maxRequestSize
如果是其它SpringBoot 1.x版本,应该是:
spring.http.multipart.maxFileSize
spring.http.multipart.maxRequestSize
另外,关于上传文件,客户端如果使用AJAX方式上传,相对于普通的AJAX请求,配置$.ajax()函数中的属性时,会有几点变化:
"data":new FormData($("#form")[0]),
"contentType":false, // jQuery不要去设置Content-Type请求头
"processData":false, // jQuery不要去处理发送的数据
例子
/**
* 允许上传的头像的最大大小
*/
public static final long AVATAR_MAX_SIZE = 750 * 1024;
/**
* 允许上传的文件的类型
*/
public static final List<String> AVATAR_TYPES = new ArrayList<>();
static {
AVATAR_TYPES.add("image/jpeg");
AVATAR_TYPES.add("image/png");
// AVATAR_TYPES.add("image/gif");
// AVATAR_TYPES.add("image/bmp");
}
@PostMapping("change_avatar")
public JsonResult<String> changeAvatar(
@RequestParam("avatar") MultipartFile avatar,
HttpSession session) {
// 检查上传的文件是否为空
if (avatar.isEmpty()) {
throw new FileEmptyException("请选择有效的头像文件");
}
// 检查上传的文件的大小是否超出了限制
if (avatar.getSize() > AVATAR_MAX_SIZE) {
throw new FileSizeException("不允许使用超过" + AVATAR_MAX_SIZE / 1024 + "KB的头像文件");
}
// 检查上传的文件的类型是否超出了限制
if (!AVATAR_TYPES.contains(avatar.getContentType())) {
throw new FileTypeException("上传的文件类型有误,仅允许上传以下格式的头像文件:" + AVATAR_TYPES);
}
// 文件夹
String parentPath = session.getServletContext().getRealPath("upload");
File parent = new File(parentPath);
if (!parent.exists()) {
parent.mkdirs();
}
// 获取原始文件名
String originalFilename = avatar.getOriginalFilename();
// 重新命名文件
String suffix = "";
int beginIndex = originalFilename.lastIndexOf(".");
if (beginIndex > 0) {
suffix = originalFilename.substring(beginIndex);
}
String filename = UUID.randomUUID().toString() + suffix;
// 用于保存上传的文件的对象
File dest = new File(parent, filename);
// 保存客户端上传的文件
try {
avatar.transferTo(dest);
} catch (IllegalStateException e) {
throw new FileStateException("文件状态异常,请重新选择文件并再次上传");
} catch (IOException e) {
throw new FileIOException("上传时出现读写错误,请重新上传");
}
// 将文件的路径存储到数据表中
String avatarPath = "/upload/" + filename;
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
userService.changeAvatar(uid, username, avatarPath);
// 响应:OK, 头像路径
return new JsonResult<>(OK, avatarPath);
}