直接进入主题
layui有很多很好用的组件给我们使用,这里前端使用layui提供的进度条组件
后端使用springboot监听传入的byte,然后返回给前端,最终实现进度条功能
layui官网 https://www.layui.com/
springboot官网 http://spring.io/projects/spring-boot
1.后端
首先定义一个进程的实体类,关于进度条的数据在这里定义
package com.yuxiao.springboot.upload.entity;
import org.springframework.stereotype.Component;
/**
* 上传进度实体类
*/
@Component
public class ProgressEntity {
private long readBytes = 0L; //到目前为止读取文件的比特数
private long allBytes = 0L; //文件总大小
private int currentIndex; //目前正在读取第几个文件
public long getReadBytes() {
return readBytes;
}
public void setReadBytes(long readBytes) {
this.readBytes = readBytes;
}
public long getAllBytes() {
return allBytes;
}
public void setAllBytes(long allBytes) {
this.allBytes = allBytes;
}
public int getCurrentIndex() {
return currentIndex;
}
public void setCurrentIndex(int currentIndex) {
this.currentIndex = currentIndex;
}
@Override
public String toString() {
return "ProgressEntity{" +
"readBytes=" + readBytes +
", allBytes=" + allBytes +
", currentIndex=" + currentIndex +
'}';
}
}
然后定义一个listener来监听上传文件的相关信息,总大小,已读取的文件等等
package com.yuxiao.springboot.upload.listener;
import com.yuxiao.springboot.upload.entity.ProgressEntity;
import org.apache.commons.fileupload.ProgressListener;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
@Component
public class UploadProgressListener implements ProgressListener {
private HttpSession session;
public void setSession(HttpSession session){
this.session = session;
ProgressEntity pe = new ProgressEntity();
session.setAttribute("uploadStatus", pe);
}
/**
* 设置当前已读取文件的进度
* @param readBytes 已读的文件大小(单位byte)
* @param allBytes 文件总大小(单位byte)
* @param index 正在读取的文件序列
*/
@Override
public void update(long readBytes, long allBytes, int index) {
ProgressEntity pe = (ProgressEntity) session.getAttribute("uploadStatus");
pe.setReadBytes(readBytes);
pe.setAllBytes(allBytes);
pe.setCurrentIndex(index);
}
}
再定义一个配置类,yua源源不断的把进度信息放到session中
package com.yuxiao.springboot.upload.config;
import com.yuxiao.springboot.upload.listener.UploadProgressListener;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Component
public class YuxiaoMultipartResolver extends CommonsMultipartResolver {
@Autowired
private UploadProgressListener progressListener;
@Override
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
String encoding = super.determineEncoding(request);
progressListener.setSession(request.getSession());
FileUpload fileUpload = prepareFileUpload(encoding);
fileUpload.setProgressListener(progressListener);
try {
List<FileItem> fileItemList = ((ServletFileUpload)fileUpload).parseRequest(request);
return super.parseFileItems(fileItemList, encoding);
} catch (FileUploadException e) {
e.printStackTrace();
}
return null;
}
}
最后写控制层,在点击文件上传之后,需要不断访问获得经度
package com.yuxiao.springboot.upload.controller;
import com.yuxiao.springboot.upload.entity.ProgressEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 文件上传及进度测试
*/
@Controller
public class UploadController {
/**
* 显示文件上传页
* @return
*/
@RequestMapping("uploadPage")
public String showUploadPage(){
return "uploadPage";
}
/*
* 文件上传
* <p>Title: upload</p>
* <p>Description: </p>
* @param file
* @return
*/
@PostMapping("upload")
@ResponseBody
public Map<String, Object> upload(MultipartFile file){
Map<String, Object> result = new HashMap<>();
if (file != null && !file.isEmpty()){
try {
file.transferTo(new File("d:/"+file.getOriginalFilename()));
result.put("code", 200);
result.put("msg", "success");
} catch (IOException e) {
result.put("code", -1);
result.put("msg", "文件上传出错,请重新上传!");
e.printStackTrace();
}
} else {
result.put("code", -1);
result.put("msg", "未获取到有效的文件信息,请重新上传!");
}
return result;
}
/**
* 获取文件上传进度
* @param request
* @return
*/
@RequestMapping("getUploadProgress")
@ResponseBody
public ProgressEntity getUploadProgress(HttpServletRequest request){
return (ProgressEntity) request.getSession().getAttribute("uploadStatus");
}
}
最后是前端页面 elem是上传的文件,bindAction是触发按钮 url是后端接口地址,data可以设置上传携带参数,progress:function中就可以获得上传进度。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" href="/plugins/layui-v2.2.5/css/layui.css" media="all">
<script src="/plugins/layui-v2.2.5/layui.js"></script>
</head>
<body>
<!--<input type="hidden" id="scopeType" name="scopeType" value="1">-->
<!--<input type="hidden" id="scopeId" name="scopeId" value="5">-->
<!--<input type="hidden" id="appCatagory" name="appCatagory" value="1">-->
<button type="button" class="layui-btn" id="addFile">
<i class="layui-icon"></i>添加文件
</button>
<button type="button" class="layui-btn" id="upload">上传</button>
<div class="layui-progress layui-progress-big" lay-showpercent="true" lay-filter="uploadProgressBar">
<div class="layui-progress-bar" lay-percent="0%"></div>
</div>
</body>
<script>
layui.use(["layer","form", "upload","jquery","element"], function () {
// 注意:为了动态显示进度条,必须加载element组件
var layer = layui.layer, upload = layui.upload, $ = layui.jquery, element = layui.element;
upload.render({
accept : "file",
elem : "#addFile",
auto : false, //关闭文件自动上传
bindAction : "#upload", //文件上传触发按钮
url : "upload",
data:{
scopeType: 1,
scopeId: 5,
appCatagory: 1
},//设置上传时携带的参数,后端可以用 String appCatagory = request.getParameter("appCatagory");接收
progress:function(value){//上传进度回调 value进度值
element.progress('uploadProgressBar', value+'%')//设置页面进度条
},
before : function (obj) {
/* var intId = setInterval(function () {
getUploadStatus(intId);
}, 1000); //每秒向服务端获取一次当前上传进度情况*/
},
done : function (res, index, upload) {
// if(res.code != 200){
// layer.open({
// icon : 2,
// skin : "layui-layer-molv",
// content : res.msg
// });
// }
console.log(res);
},
error : function (res) {
}
});
});
</script>
</html>
实现效果