转载:https://blog.csdn.net/cyh1111/article/details/52960233
实现
实现带进度条的文件上传一般都是服务器端计算文件上传进度,客户端轮询读取显示的方式。
Commons-fileupload组件自带了文件上传进度的监听器,类FileUploadBase提供了它的set方法。
SpringMVC没有实现监听器,所以如果要监听的话得自己扩展CommonsMultipartResolver类,加入代码设置自己实现的监听器
ProgressListener是一个接口,我们需要自己实现它的update方法,参数pBytesRead表示已经上传到服务器的字节数,pContentLength表示所有文件的总大小,pItems表示第几个文件
1、实现ProgressListener
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;
}
}
2、实现MultipartResolver
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<FileItem> 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);
}
}
}
3、Progress 实体类
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 + "]";
}
}
4、SpringMVC Controller方法
/**
* 异步上传处理
* @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;
}
5、配置CustomMultipartResolver
在SpringMVC配置文件中配置CustomMultipartResolver,支持文件上传
<!-- 支持上传文件 -->
<bean id="multipartResolver" class="com.lead.sy.web.upload.CustomMultipartResolver"/>
6、上传页面
<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="button" class="btn btn-success" value="上传" />
</div>
</div>
上传控制JS代码
<script>
$(function () {
// 默认上传按钮不可用
$("#btnUpload").attr("disabled", true);
// 弹出上传Model
$("#activeUpload").click(function(){
$("#uploadModal").modal("show");
})
// 上传按钮点击事件
$("#btnUpload").click(function() {
//上传按钮修改为可用
$(this).attr("disabled", true);
uploadFunction();
})
// 文件修改时
$("#uploadFile").change(function() {
$("#btnUpload").val("上传");
var file = $(this).prop("files");
if (file.length != 0) {
$("#btnUpload").attr("disabled", false);
}
});
//文件上传
function uploadFunction() {
var uploadFile = $("#uploadFile").get(0).files[0]; //获取文件对象
// FormData 对象
var form = new FormData();
form.append("file", uploadFile); // 文件对象
var uploadUrl = "<%=path%>/file/upload";//异步上传地址
$.ajax({
cache: false,
type: "POST",
url: uploadUrl,
contentType: false,
processData: false,
data: form,
xhr: function(){ //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
myXhr = $.ajaxSettings.xhr();
if(progressFunction && myXhr.upload) { //检查进度函数和upload属性是否存在
//绑定progress事件的回调函数
myXhr.upload.addEventListener("progress",progressFunction, false);
}
return myXhr; //xhr对象返回给jQuery使用
},
error: function(request) {
alert("Connection error");
},
success: function(data) {
$("input[name=companyLicenseImg]").val(data);
$("#licenseImg").attr("src","<%=path%>"+data); //将后台返回图片路径设置给IMG,显示图片
$("#licenseImg").attr("width","100");
$("#activeUpload").val("重新上传");
$("#btnUpload").attr("disabled", false);
$("#btnUpload").val("上传");
$("#uploadModal").modal("hide");
}
});
}
//进度条控制
function progressFunction(evt) {
if (evt.lengthComputable) {
var completePercent = Math.round(evt.loaded / evt.total * 100)+ "%";
$("#btnUpload").val("正在上传,进度:" + completePercent);
}
}
});
</script>