最近在做一个小项目,框架使用现在主流的:SpringMVC(4.1)+Spring(4.1)+MyBatis,前端采用基于Bootstrap封装的模板AdminLTE(2.3.6)。需要实现图片异步上传,了解SpringMVC的文件上传功能是在commons-fileupload组件提供的功能上面做了一些封装来实现,使文件上传开发更容易方便。代码越写越少了,很方便。
这里主要是实现了文件异步上传,后台将文件相对路径返回到页面,显示出来,功能比较简单。本文假设已经将SSM框架配置完毕。
实现带进度条的文件上传一般都是服务器端计算文件上传进度,客户端轮询读取显示的方式。
Commons-fileupload组件自带了文件上传进度的监听器,类FileUploadBase提供了它的set方法。
SpringMVC没有实现监听器,所以如果要监听的话得自己扩展CommonsMultipartResolver类,加入代码设置自己实现的监听器
ProgressListener是一个接口,我们需要自己实现它的update方法,参数pBytesRead表示已经上传到服务器的字节数,pContentLength表示所有文件的总大小,pItems表示第几个文件
FileUploadProgressListener实现ProgressListener,将上传进度保存到session中。
使用注解
@Component
public class FileUploadProgressListener implements ProgressListener {
private HttpSession session;
@Override
public void update(long bytesRead, long contentLength, int items) {
//设置上传进度
ProgressBean progress = new ProgressBean(bytesRead, contentLength, items);
//将上传进度保存到session中
session.setAttribute("progress", progress);
}
public void setSession(HttpSession session){
this.session = session;
}
}
CustomMultipartResolver继承CommonsMultipartResolver,需要在每一次上传请求中设定处理上传进度的监听器,并处理文件上传。
将第一步中FileUploadProgressListener注入进来
public class CustomMultipartResolver extends CommonsMultipartResolver {
//FileUploadProgressListener 自动注入
@Resource
private FileUploadProgressListener progressListener;
@Override
public MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
//FileUploadProgressListener中注入session
progressListener.setSession(request.getSession());
fileUpload.setProgressListener(progressListener);
try {
List fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems, encoding);
} catch (FileUploadBase.SizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
} catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
}
}
public class ProgressBean {
private long bytesRead;
private long contentLength;
private long items;
public ProgressBean(long bytesRead, long contentLength, long items) {
super();
this.bytesRead = bytesRead;
this.contentLength = contentLength;
this.items = items;
}
public long getBytesRead() {
return bytesRead;
}
public void setBytesRead(long bytesRead) {
this.bytesRead = bytesRead;
}
public long getContentLength() {
return contentLength;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
public long getItems() {
return items;
}
public void setItems(long items) {
this.items = items;
}
@Override
public String toString() {
return "ProgressBean [bytesRead=" + bytesRead + ", contentLength="
+ contentLength + ", items=" + items + "]";
}
}
/**
* 异步上传处理
* @param request
* @param response
* @param file
* @return 返回上传文件相对路径及名称
* @throws IOException
*/
@RequestMapping(value="/file/upload", produces = "text/json;charset=UTF-8")
@ResponseBody
public String uploadFileHandler(HttpServletRequest request, @RequestParam("file") MultipartFile file){
//上传文件每日单独保存
String path = "/upload/"+DateUtil.getNowDate()+"/";
if (file.getSize() > 0) {
//获取绝对路径
String uploadPath = request.getSession().getServletContext().getRealPath(path);
try {
//创建目标文件
File targetFile = new File(uploadPath, file.getOriginalFilename());
if (!targetFile.exists()) {
targetFile.mkdirs();
}
file.transferTo(targetFile);
JSON.toJSONString(path+file.getOriginalFilename());
} catch (Exception e) {
}
}
return null;
}
在SpringMVC配置文件中配置CustomMultipartResolver,支持文件上传
<bean id="multipartResolver" class="com.lead.sy.web.upload.CustomMultipartResolver"/>
定义上传Modal
<div id="uploadModal" class="modal fade" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×button>
div>
<div class="modal-body">
<div class="form-group" id="passwordDiv">
<label>选择营业执照照片label>
<input class="form-control" type="file" id="uploadFile">
div>
<div class="form-group">
<input id="btnUpload" type="submit" name="submit" class="btn btn-success" value="上传" />
div>
div>
div>
div>
div>
上传控制JS代码