利用 Spring MVC 实现文件上传功能,离不开对 MultipartResolver 的设置。MultipartResolver 这个类,你可以 将其视为 Spring MVC 实现文件上传功能时的工具类,这个类也只会在文件上传中发挥作用。在配置了具体实现类之后,Spring MVC 中的 DispatcherServlet 在处理请求时会调用 MultipartResolver 中的方法判断此请求是不是文件上传请求。如果是,DispatcherServlet 将调用 MultipartResolver 的 resolveMultipart(request) 方法对该请求对象进行装饰并返回一个新的 MultipartHttpServletRequest 供后继处理流程使用。注意,此时的请求对象会由 HttpServletRequest 类型转换成 MultipartHttpServletRequest 类型,这个类中会包含所上传的文件对象,可供后续流程直接使用,而无需自行在代码中实现对文件内容的读取逻辑。
当收到请求时,DispatcherServlet 的 checkMultipart() 方法会调用 MultipartResolver 的 isMultipart() 方法判断请求中是否包含文件。
如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart() 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest(继承了 HttpServletRequest)对象中,最后传递给 Controller 控制器。
spring-mvc.xml
如下设置 MultipartResolver,我们使用的是仍是 CommonsMultipartResolver 实现类:
<!--文件上传 10M=10*1024*1024(B)=1048 5760 bytes 104857600 134217728 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设定默认编码 -->
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 设定文件上传的最大值-->
<property name="maxUploadSize" value="1048576000" />
</bean>
后端示例代码1:
/**
* 图片上传
* @param request
* @param path
* @param dirPath
* @return
* @throws IOException
*/
@Override
public String uploadLogo(HttpServletRequest request, String path,
String dirPath) throws IOException {
String flag = "";
// 获取解析器
ServletContext servletContext = request.getSession().getServletContext();
CommonsMultipartResolver resolver = new CommonsMultipartResolver(servletContext);
// 判断是否是文件
if (!resolver.isMultipart(request)) {
return "500";
}
// 进行转换
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) (request);
// 获取所有文件名称
Iterator<String> it = multiRequest.getFileNames();
while (it.hasNext()) {
// 根据文件名称取文件
MultipartFile file = multiRequest.getFile(it.next());
if (!file.isEmpty()) {
String type = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1, file.getOriginalFilename().length());
Random r = new Random();
log.info("图片类型:" + type);
log.info(path);
if (!"png".equals(type)) {
throw new RestException(ResultEnum.FORMAT_IS_ERROR.getCode(),
"上传的图片格式不正确");
}
// 上传文件名
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String filename = sdf.format(new Date()) + r.nextInt(100) + ".png";
File filepath = new File(path, filename);
// 判断路径是否存在,如果不存在就创建一个
if (!filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
// 将上传文件保存到一个目标文件当中
file.transferTo(new File(path + File.separator + filename));
flag = dirPath + "/" + filename;
} else {
flag = "500";
}
}
return flag;
}
//调用
String msg = sysThemeServer.uploadLogo(request, "C:/sysLogo",
"sysLogo");
后端示例代码2:
通过前文中的分析,可知文件对象已被封装到 MultipartFile 对象中,在代码中可以直接使用此文件对象,之后调用 File 相关方法将文件存储到 upload 目录下,代码如下:
public Result upload(HttpServletRequest request, @RequestParam("file") MultipartFile file) throws IOException {
ServletContext sc = request.getSession().getServletContext();
String dir = sc.getRealPath("/upload");
String type = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1, file.getOriginalFilename().length());
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
Random r = new Random();
String imgName = "";
if ("jpg".equals(type)) {
imgName = sdf.format(new Date()) + r.nextInt(100) + ".jpg";
} else if ("png".equals(type)) {
imgName = sdf.format(new Date()) + r.nextInt(100) + ".png";
} else if ("jpeg".equals(type)) {
imgName = sdf.format(new Date()) + r.nextInt(100) + ".jpeg";
} else if ("gif".equals(type)) {
imgName = sdf.format(new Date()) + r.nextInt(100) + ".gif";
} else {
return null;
}
//将文件流写入到磁盘中
FileUtils.writeByteArrayToFile(new File(dir, imgName), file.getBytes());
//返回文件路径
return Result.ok().put("url", "/upload/" + imgName);
}