springboot带有进度条的上传
Posted zincredible
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot带有进度条的上传相关的知识,希望对你有一定的参考价值。
1.pom.xml配置
application.yml
server: port: 7007 tomcat: uri-encoding : UTF-8 spring: application: name: push-svc-demo thymeleaf: encoding: UTF-8 cache: false mode: LEGACYhtml5 data: mongodb: host: 127.0.0.1 port: 27017 database: mydb debug: false
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <!--添加文件上传支持--> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <!--添加html5支持--> <dependency> <groupId>net.sourceforge.nekohtml</groupId> <artifactId>nekohtml</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
2.进程类
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; } }
3.监听类
@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); } }
4.
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); progressListener.setSession(request.getSession());// 问文件上传进度监听器设置session用于存储上传进度 fileUpload.setProgressListener(progressListener);// 将文件上传进度监听器加入到 fileUpload 中 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); } } }
5.控制器
@RestController public class FileController { // private final static Logger logger = // LoggerFactory.getLogger(FileController.class); @Autowired private PushMsgRepository pushRep; public static void log(Object o) { System.out.println(o); } @RequestMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { if (file.isEmpty()) { return "文件为空"; } // 获取文件名 String fileName = file.getOriginalFilename(); System.out.println("上传的文件名为:" + fileName); // 获取文件的后缀名 // String suffixName = fileName.substring(fileName.lastIndexOf(".")); // logger.info("上传的后缀名为:" + suffixName); // 文件上传后的路径 String filePath = null; try { filePath = new File("").getCanonicalPath() + "/tmp/uploadFile/"; } catch (IOException e1) { e1.printStackTrace(); } String tagFilePath = filePath + CommonUtil.getCurrentTime() + fileName; System.out.println("存储路径为:" + tagFilePath); // 解决中文问题,liunx下中文路径,图片显示问题 // fileName = UUID.randomUUID() + suffixName; File dest = new File(tagFilePath); // 检测是否存在目录 if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } try { file.transferTo(dest); PushMsgEntity pushInfo=new PushMsgEntity(); pushInfo.setFilePath(fileName); pushInfo.setUserName("深圳"); pushRep.save(pushInfo); return fileName + "推送成功"; } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return fileName + "推送失败"; } @RequestMapping("/uploads") public Map<String, Object> uploadFiles(HttpServletRequest request) { Map<String, Object> result = new HashMap<String, Object>(); List<MultipartFile> files2 = ((MultipartHttpServletRequest) request).getFiles("file"); BufferedOutputStream stream = null; String uploadPath = "upload/"; validatePath(uploadPath); result.put("fileLength", files2.size()); int i = 0; for (MultipartFile file : files2) { String originalFilename = file.getOriginalFilename(); i++; validateType(uploadPath); if (!file.isEmpty()) { try { byte[] bytes = file.getBytes(); stream = new BufferedOutputStream(new FileOutputStream(new File(uploadPath, originalFilename))); stream.write(bytes); result.put("file" + i, uploadPath + originalFilename); stream.close(); } catch (Exception e) { result.put("message", originalFilename + "You failed to upload => " + e.getMessage()); } } else { result.put("message", originalFilename + "You failed to upload because the file was empty."); } } return result; } /** * 验证上传的文件类型 * * @return */ private Map<String, Object> validateType(String path) { Map<String, Object> result = new HashMap<String, Object>(); File file = new File(path); if (!file.exists()) file.mkdirs(); return result; } /** * 验证上传的文件路径,没有则创建 * * @return */ private void validatePath(String path) { File file = new File(path); if (!file.exists()) file.mkdirs(); } @RequestMapping("/showPushInfo") public List<PushMsgEntity> showAllPushInfo() { return pushRep.findAll(new Sort(Direction.DESC, "generateTime")); } }
6.启动类
@EnableAutoConfiguration(exclude = { MultipartAutoConfiguration.class }) @SpringBootApplication public class Application extends SpringBootServletInitializer { /* * 将 multipartResolver 指向我们刚刚创建好的继承 CommonsMultipartResolver 类的自定义文件上传处理类 */ @Bean(name = "multipartResolver") public MultipartResolver multipartResolver() { CustomMultipartResolver customMultipartResolver = new CustomMultipartResolver(); return customMultipartResolver; } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
7.页面测试
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Upload Files using XMLHttpRequest - Minimal</title> <link rel="stylesheet" href="/vendor/bootstrap/css/bootstrap.css" /> <script src="/vendor/jquery/jquery-1.10.2.min.js"></script> <script src="/vendor/bootstrap/js/bootstrap.min.js"></script> </head> <body class="container"> <div id="wrapper"> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <h1 class="page-header">数据推送系统服务端</h1> </div> <!-- /.col-lg-12 --> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading">数据推送系统服务端</div> <div class="panel-body"> <div class="row"> <div class="col-lg-6"> <form role="form" action="javascript:void(0)"> <div class="form-group"> <label>模型文件选择</label> <input id="batchFile" class="btn btn-primary" name="file" type="file" /> <div id="showFieInfo" class="form-group"> <label id="upfileName"></label><br /> <label id="upfileSize"></label><br /> <label id="upfileType"></label><br /> </div> <!-- <label for="name">选择推送地域</label> <select class="form-control"> <option>深圳</option> <option>东莞</option> <option>印度</option> </select> --> <label for="name">选择推送的地域(可多选)</label> <select multiple class="form-control"> <option>西安</option> <option>深圳</option> <option>东莞</option> <option>印度</option> <option>宜宾</option> <option>武汉</option> <option>宜宾</option> </select> </div> <div class="progress progress-striped active" style="display: none"> <div id="progressBar" class="progress-bar progress-bar-success" role="progressbar" aria-valuemin="0" aria-valuenow="0" aria-valuemax="100" style="width: 0%"></div> </div> <div class="form-group"> <button id="batchUploadBtn" type="submit" class="btn btn-primary">上传文件</button> <label id="showInfo"></label> </div> <div class="form-group"> <img id="imageUpload" alt="上传的后数据" src="" width="100%" /> </div> </form> </div> </div> <!-- /.row (nested) --> </div> <!-- /.panel-body --> </div> <!-- /.panel --> </div> <!-- /.col-lg-12 --> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> <div id="wrapper"> <div id="page-wrapper"> <div class="row"> <div class="col-lg-12"> <h1 class="page-header">推送历史信息</h1> </div> <!-- /.col-lg-12 --> </div> <!-- /.row --> <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading">推送历史记录</div> <div class="panel-body"> <div id=""> <table id="showPushInfo" class="table table-striped table-hover "> </table> </div> </div> <!-- /.panel-body --> </div> <!-- /.panel --> </div> <!-- /.col-lg-12 --> </div> <!-- /.row --> </div> <!-- /#page-wrapper --> </div> <!-- /#wrapper --> </body> <script type="text/javascript"> /* <![CDATA[> */ $(document) .ready( function() { $("#batchImportBtn").click(function() { $(‘#batchImportModal‘).modal(‘show‘); }); var base = $("#base").val(); base = ‘‘; showPushMsgInfo(); // 上传按钮 $("#batchUploadBtn").attr(‘disabled‘, true); $("#showFieInfo").attr(‘disabled‘, true); $("#showInfo").text(‘‘); // 上传文件按钮点击的时候 $("#batchUploadBtn").click(function() { // 进度条归零 $("#progressBar").width("0%"); // 上传按钮禁用 $(this).attr(‘disabled‘, true); // 进度条显示 $("#progressBar").parent().show(); $("#progressBar").parent().addClass("active"); // 上传文件 UpladFile(); }) // 文件修改时 $("#batchFile") .change( function() { $("#batchUploadBtn").text( "数据文件已存在,请推送"); var processbar = $("#progressBar"); processbar.width("0%") processbar.text(‘‘); $("#showInfo").text(‘‘); var file = $(this).prop(‘files‘); if (file.length != 0) { $("#batchUploadBtn").attr( ‘disabled‘, false); } var fileObj = $("#batchFile") .get(0).files[0]; // js 获取文件对象 if (fileObj) { var fileSize = 0; if (fileObj.size > 1024 * 1024) { fileSize = (Math .round(fileObj.size / (1024 * 1024))) .toString() + ‘MB‘; } else { fileSize = (Math .round(fileObj.size / 1024)) .toString() + ‘KB‘; } console.log(fileObj.size) $("#upfileName").text( ‘文件名:‘ + fileObj.name); $("#upfileSize").text( ‘文件大小:‘ + fileSize); $("#upfileType").text( ‘文件类型:‘ + fileObj.type); $("#showFieInfo").attr( ‘disabled‘, false); } }); function UpladFile() { var fileObj = $("#batchFile").get(0).files[0]; // js 获取文件对象 console.log("上传的文件:" + fileObj); var FileController = base + "/upload"; // 接收上传文件的后台地址 // FormData 对象 var form = new FormData(); // form.append("author", "hooyes"); // 可以增加表单数据 form.append("file", fileObj); // 文件对象 // XMLHttpRequest 对象 var xhr = new XMLHttpRequest(); xhr.open("post", FileController, true); xhr.onload = function() { // ShowSuccess("上传完成"); //alert("上传完成"); $("#batchUploadBtn").attr(‘disabled‘, false); //$("#batchUploadBtn").text("上传"); $("#progressBar").parent().removeClass("active"); //$("#progressBar").parent().hide(); $("#batchUploadBtn").text("文件推送") //$(‘#myModal‘).modal(‘hide‘); }; xhr.upload.addEventListener("progress", progressFunction, false); xhr.addEventListener("load", uploadComplete, false); xhr.addEventListener("error", uploadFailed, false); xhr .addEventListener("abort", uploadCanceled, false); xhr.send(form); } function progressFunction(evt) { var progressBar = $("#progressBar"); if (evt.lengthComputable) { var completePercent = Math.round(evt.loaded / evt.total * 100) + "%"; progressBar.width(completePercent); progressBar.text(completePercent); $("#batchUploadBtn").text( "文件推送中 " + completePercent); } } function formatDate(now) { var year = now.getFullYear(); var month = now.getMonth() + 1; var date = now.getDate(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); var mill = now.getMilliseconds(); return year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second+":"+mill; } function showPushMsgInfo() { var $table = $("#showPushInfo"); $.ajax({ url : "/showPushInfo", type : "get", async : true, success : function(result) { $table.html(""); $.each(result,function(index,item){ console.log(index) var $tr = $(‘<tr>‘); $.each(item,function(name,val){ if(name==‘generateTime‘) { val=formatDate(new Date(val)); } var $td = $(‘<td>‘).html(val); $tr.append($td); }); $table.append($tr); }); //$("#showPushInfo").text(JSON.stringify(result)) }, error : function(result) { $("#showInfo").text(‘获取推送信息产生异常:‘+JSON.stringify(result)); } }); } function uploadComplete(evt) { $("#showInfo").text(evt.target.responseText); showPushMsgInfo(); } function uploadFailed(evt) { $("#showInfo").text("上传失败,上传文件发生了错误:"+evt.target.responseText); } function uploadCanceled(evt) { $("#showInfo").text("上传取消,上传被用户取消或者浏览器断开连接:"+evt.target.responseText); } }); /*]]>*/ </script> </html>
以上是关于springboot带有进度条的上传的主要内容,如果未能解决你的问题,请参考以下文章
带有进度条的 jQuery ajax 上传 - 没有 flash
Flutter 上传带有进度条的大文件。 App 和 Web 都支持
使用 HTML5 和 Javascript 录制/上传带有进度条的固定长度视频