这篇文章主要介绍了springboot带有进度条的上传功能,结合完整实例形式分析了springboot带进度条上传的原理、实现步骤与相关操作技巧,需要的朋友可以参考下
本文实例讲述了springboot带有进度条的上传功能。分享给大家供大家参考,具体如下:
一、说明
最近要做文件上传,在网上找了很久都没有一个全面的示例,特此记录下来分享给大家。
1.文件上传接口可按照springboot默认实现,也可用commons-fileupload组件,本示例使用springboot默认文件上传 2.最后也有commons-fileupload组件接口示例
2.重点在前端JS实现(也可以使用ajax上传),参考了网上大量上传文件显示进度条博客以及技术方案,在此做了一个统一的总结,方便后续使用
3.这仅仅是一个示例,大家可根据实际需要改进。
二、前端代码
<title>文件上传</title> <br /><span id="time"></span><div class="row"> <br /><div class="col-lg-5" style="padding-left: 0;padding-right: 0;margin-bottom: 0px"> <div class="progress progress-striped active"> <div id="progressBar" class="progress-bar progress-bar-success" role="progressbar" style="width: 20%"></div></div></div><!-- 显示上传速度 --><div id="showInfo" class="col-lg-2">0KB/s</div></div><!-- 显示文件信息 --><div id="showFieInfo" class="row"> <label></label><br /><label></label><br /><label></label><br /></div><div class="row"> </div>
三、对上传代码进行组件化封装
UploadCommon.js
/** * 上传文件公共组件 * * @param url 上传地址 * @param processBar 进度条 jquery获取的页面组件 * @param speedLab 显示上传速度Label jquery获取的页面组件 * @param uploadBtn 上传按钮 jquery获取的页面组件 * @param cancelBtn 取消上传按钮 jquery获取的页面组件 * @param callBack 上传完成回调函数 上传完成后的回调函数,可以不传 * @author * @returns */ function UploadCommon(url, processBar, speedLab, uploadBtn, cancelBtn, callBack){ function init() { // 每次回调监测上传开始时间 var startTime = null // 已上传文件大小 var oloaded = null var xhr = new XMLHttpRequest() function setProgress(w) { processBar.width(w + '%'); processBar.text(w + '%'); } function progressMonitor(evt){ if (evt.lengthComputable) { var completePercent = Math.round(evt.loaded / evt.total * 100) setProgress(completePercent) var nowTime = new Date().getTime() // 计算出上次调用该方法时到现在的时间差,单位为s var pertime = (nowTime - startTime) / 1000 // 重新赋值时间,用于下次计算 startTime = new Date().getTime() // 计算该分段上传的文件大小,单位b var perload = evt.loaded - oloaded // 重新赋值已上传文件大小,用以下次计算 oloaded = evt.loaded // 上传速度计算,单位b/s var speed = perload / pertime var bspeed = speed // 单位名称 var units = 'bit/s'if (speed / 1024 > 1) { speed = speed / 1024 units = 'Kb/s' } if (speed / 1024 > 1) { speed = speed / 1024 units = 'Mb/s' } speed = speed.toFixed(1); // 剩余时间 var resttime = ((evt.total - evt.loaded) / bspeed).toFixed(1) speedLab.html(speed + units + ',剩余时间:' + resttime + 's') } } // 上传成功后回调 function uploadComplete(evt) { uploadBtn.attr('disabled', false) var status = evt.currentTarget.status if (status == 401) { alert('请登录后再上传') return } if (status == 403) { alert('无权限操作') return } if (status != 200) { alert('上传异常,错误码' + status) return } var response=JSON.parse(evt.currentTarget.response) if (response.code!='200') { alert('上传处理异常' + response.msg) return } console.log('上传成功') if ( callBack != null && typeof callBack != 'undefined') { callBack() } }; // 上传失败回调 function uploadFailed(evt) { alert('上传处理失败' + evt.target.responseText) } // 终止上传 function cancelUpload() { xhr.abort() } // 上传取消后回调 function uploadCanceled(evt) { alert('文件上传已终止:' + evt.target.responseText) } // 添加取消上传事件 cancelBtn.click(function() { uploadBtn.attr('disabled', false) cancelUpload(); }) this.uploadFile = function(formData) { // 上传按钮禁用 uploadBtn.attr('disabled', true); setProgress(0) // true为异步处理 xhr.open('post', url, true) // 上传开始执行方法 xhr.onloadstart = function() { console.log('开始上传') // 设置上传开始时间 startTime = new Date().getTime() // 已上传的文件大小为0 oloaded = 0 } xhr.upload.addEventListener('progress', progressMonitor, false) xhr.addEventListener("load", uploadComplete, false) xhr.addEventListener("error", uploadFailed, false) xhr.addEventListener("abort", uploadCanceled, false) xhr.send(formData); } this.setProgressValue=function(w){ processBar.width(w + '%') processBar.text(w + '%') } } return new init() }
调用
$(document).ready(function() { var addVersionBtn=$('#addVersionBtn') //<button> var cancelUploadBtn=$('#cancelUploadBtn') //<button> var fileInput=$("#filewareFile") // var processBar = $("#progressBar"); //div var fileNameLab=$("label[name=upfileName]") //<label> var fileSizeLab=$("label[name=upfileSize]") //... var fileTypeLab=$("label[name=upfileType]") //... var speedLab=$("#showSpeed") //<label> var url='/api/file' //获取文件上传实例 var upload=UploadCommon(url,processBar,speedLab,addVersionBtn,cancelUploadBtn,initPageInfo) // 文件选择框变更事件 fileInput.change(function() { var fileObj = fileInput.get(0).files[0]; // js获取文件对象 if (fileObj) { var fileSize = getSize(fileObj.size); fileNameLab.text('文件名:' + fileObj.name); fileSizeLab.text('文件大小:' + fileSize); fileTypeLab.text('文件类型:' + fileObj.type); addVersionBtn.attr('disabled', false); } }); // 点击上传固件事件 addVersionBtn.click(function(){ var versionInfo=$('#version').val() var file = fileInput.get(0).files[0] var strategyInfo=$('#versionType').val() if(file==null){ alert("固件文件不能为空") return } if(versionInfo==''){ alert("版本号不能为空") return } if(strategyInfo==''){ alert("升级策略不能为空") return } // 创建提交数据 var formData = new FormData(); formData.append('firmFile', fileInput.get(0).files[0]); formData.append('version', versionInfo); formData.append('strategy', strategyInfo); // 上传文件 upload.uploadFile(formData) }) });
四,服务端接口
1.springboot默认实现
pom.xml
4.0.0com.demodemo0.0.1-SNAPSHOT org.springframework.bootspring-boot-starter-parent1.5.10.RELEASE UTF-8UTF-81.8 org.springframework.bootspring-boot-devtoolstrue org.springframework.bootspring-boot-starter-web org.springframework.bootspring-boot-starter-thymeleaf net.sourceforge.nekohtmlnekohtml org.springframework.bootspring-boot-starter-testtest<!-- 添加Swagger2依赖,用于生成接口文档 --> io.springfoxspringfox-swagger22.7.0 io.springfoxspringfox-swagger-ui2.7.0<!--end--> org.springframework.bootspring-boot-maven-plugin
application.yml
server: port: 8080 tomcat: uri-encoding: UTF-8 application: name: demo thymeleaf: encoding: UTF-8 cache: true mode: LEGACYHTML5 devtools: restart: enabled: true http: multipart: maxFileSize: 500Mb maxRequestSize: 500Mb location: D:/tmp debug: false
接口:
@PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { if (file == null || file.isEmpty()) { return "file is empty"; } // 获取文件名 String fileName = file.getOriginalFilename(); // 文件存储路径 String filePath = "D:/data/" + UUID.randomUUID().toString().replaceAll("-", "") + "_" + fileName; logger.info("save file to:" + filePath); File dest = new File(filePath); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } try { file.transferTo(dest); return "success"; } catch (Exception e) { e.printStackTrace(); } return "fail"; }
启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication @EnableTransactionManagement public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
2.使用commons-fileupload上传组件
application.yml
server: port: 8080 tomcat: uri-encoding : UTF-8 spring: application: name: svc-demo thymeleaf: encoding: UTF-8 cache: false mode: LEGACYHTML5 debug: false
pom .xml
org.springframework.bootspring-boot-starter-parent1.5.10.RELEASE UTF-8UTF-81.8 org.springframework.bootspring-boot-devtoolstrue org.springframework.bootspring-boot-starter-web org.springframework.bootspring-boot-starter-thymeleaf org.springframework.bootspring-boot-starter-testtest<!--添加文件上传支持--> commons-iocommons-io2.4 commons-fileuploadcommons-fileupload1.3.1<!--添加html5支持--> net.sourceforge.nekohtmlnekohtml org.springframework.bootspring-boot-maven-plugin
进程类
public class Progress{ private long bytesRead; //已读取文件的比特数 private long contentLength;//文件总比特数 private long 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; } }
监听类
@Component public class FileUploadProgressListener implements ProgressListener{ private HttpSession session; public void setSession(HttpSession session){ this.session=session; Progress status = new Progress();//保存上传状态 session.setAttribute("status", status); } @Override public void update(long bytesRead, long contentLength, int items) { Progress status = (Progress) session.getAttribute("status"); status.setBytesRead(bytesRead); status.setContentLength(contentLength); status.setItems(items); } }
文件上传处理类
public class CustomMultipartResolver extends CommonsMultipartResolver{ // 注入第二步写的FileUploadProgressListener @Autowired private FileUploadProgressListener progressListener; public void setFileUploadProgressListener(FileUploadProgressListener progressListener){ this.progressListener = progressListener; } @Override public MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException{ String encoding = determineEncoding(request); FileUpload fileUpload = prepareFileUpload(encoding); //fileUpload.setFileSizeMax(1024 * 1024 * 500);// 单个文件最大500M //fileUpload.setSizeMax(1024 * 1024 * 500);// 一次提交总文件最大500M progressListener.setSession(request.getSession());// 问文件上传进度监听器设置session用于存储上传进度 fileUpload.setProgressListener(progressListener);// 将文件上传进度监听器加入到 fileUpload 中 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); } } }
控制器
@RestController public class FileController{ @PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { if (file.isEmpty()) { return "文件为空"; } // 获取文件名 String fileName = file.getOriginalFilename();// 文件上传后的路径 // 文件上传后的路径 String filePath = null; try{ filePath = new File("").getCanonicalPath() + "/tmp/uploadFile/"; } catch (IOException e){ e.printStackTrace(); } //存储路径 String tagFilePath = filePath + CommonUtil.getCurrentTime() + fileName; File dest = new File(tagFilePath); // 检测是否存在目录 if (!dest.getParentFile().exists()){ dest.getParentFile().mkdirs(); } try{ file.transferTo(dest); } catch (IllegalStateException e){ e.printStackTrace(); } catch (IOException e){ e.printStackTrace(); } return fileName + "上传失败"; } }
启动类
//注意取消自动Multipart配置,否则可能在上传接口中拿不到file的值 @EnableAutoConfiguration(exclude = { MultipartAutoConfiguration.class }) @SpringBootApplication public class Application extends SpringBootServletInitializer{ //注入自定义的文件上传处理类 @Bean(name = "multipartResolver") public MultipartResolver multipartResolver() { CustomMultipartResolver customMultipartResolver = new CustomMultipartResolver(); return customMultipartResolver; } @Ove<p style="color:transparent">来源gao!%daima.com搞$代*!码网</p>rride protected SpringApplicationBuilder configure(SpringApplicationBuilder application){ return application.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); }
更多关于java相关内容感兴趣的读者可查看本站专题:《》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。
以上就是springboot带有进度条的上传功能完整实例的详细内容,更多请关注gaodaima搞代码网其它相关文章!