1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > layui 文件实现分片上传和 断点续传 和 急速秒传 SpringBoot JAVA

layui 文件实现分片上传和 断点续传 和 急速秒传 SpringBoot JAVA

时间:2019-01-02 20:25:15

相关推荐

layui 文件实现分片上传和 断点续传 和 急速秒传 SpringBoot JAVA

一丶分片上传

分片上传 slice()这个方法功能是将一个文件切割为一系列特定大小的小数据片,分别将这些小数据片分别上传到服务端,全部上传完后再由服务端将这些小数据片合并成为一个完整的资源。

二 丶 断点续传

断点续传需要使用 MD5生成一个文件的唯一码,后台数据库会存下上传记录也就是分片位置和总分片数。

思路就是每次上传之前先拿到MD5的唯一码去数据库查到文件的上传记录以及分片位置和总片数返回给前端从下一个分片开始上传。

三丶 急速秒传

上传之前去拿到MD5唯一码去查数据如果已经有了文件就返回给前台,不用重新上传实现急速秒传…

后端就是每次上传时判断下标等不等文件总片数

等于时就去合并文件

不等于继续上传下个分片文件

前端代码

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><link type="text/css" rel="stylesheet" href="/static/layui-v2.5.5/css/layui.css"><!-- <link rel="stylesheet" href="lib/layui-v2.5.5/css/layui.css" media="all">--><style type="text/css">.loading{position:fixed;width:300px;left:50%;margin-left:-150px;top:200px;height:18px;border-radius:10px;z-index:9999;overflow:hidden;display:none;}.barmy{background:#5FB878;}#bigdiv{width: 600px;height: 600px;position: absolute;top: 50%;left: 50%;-webkit-transform: translate(-50%, -50%);-moz-transform: translate(-50%, -50%);-ms-transform: translate(-50%, -50%);-o-transform: translate(-50%, -50%);transform: translate(-50%, -50%);box-shadow: 0 2px 4px rgba(0, 0, 0, .12),0 0 6px rgba(0, 0, 0, .04);}#fileUpload{position: absolute;top: 80%;left: 50%;-webkit-transform: translate(-50%, -50%);-moz-transform: translate(-50%, -50%);-ms-transform: translate(-50%, -50%);-o-transform: translate(-50%, -50%);transform: translate(-50%, -50%);box-shadow: 0 2px 4px rgba(0, 0, 0, .12),0 0 6px rgba(0, 0, 0, .04);}</style></head><body><div id="bigdiv"><button type="button" class="layui-btn" id="fileUpload">上传</button><div id="mm"></div><div class="loading"><div class="layui-progress layui-progress-big" lay-showpercent="true" lay-filter="uploadProgress"><div class="layui-progress-bar barmy" lay-percent="0%"></div></div></div></div></body><script src="/static/layui-v2.5.5/layui.js"></script><script src="/static/layui-v2.5.5/sparkmd5.js"></script><script type="text/javascript">/*** @param file 文件* @param chunkSize 分片大小* @returns Promise*/function getmd5(file, chunkSize) {return new Promise((resolve, reject) => {let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;let chunks = Math.ceil(file.size / chunkSize);let currentChunk = 0;let spark = new SparkMD5.ArrayBuffer();let fileReader = new FileReader();fileReader.onload = function(e) {spark.append(e.target.result);currentChunk++;if (currentChunk < chunks) {loadNext();} else {let md5 = spark.end();resolve(md5);// console.log(md5);}};fileReader.onerror = function(e) {reject(e);};function loadNext() {let start = currentChunk * chunkSize;let end = start + chunkSize;if (end > file.size){end = file.size;}fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));}loadNext();});}layui.use([ 'upload', 'element'], function () {var $ = layui.jquery, upload = layui.upload;var element = layui.element;/*** start end 文件切割的开始和结束位置* switchC 开关* updateobj 存出layui的update对象方便后面再掉上传*/let fileShardIndex,start,end,fileSize,fileKey,data,fileShard,fileShardTotal,fileName,fileSuffix,fileShardSize,fileY,updateobj,switchC;upload.render({elem: '#fileUpload',url: '/bigupdate', //处理上传文件接口accept: 'file',auto: false,acceptMime: '*',//允许上传的文件类型ext: 'mp4|jpg', //choose: function (obj) {fileShardSize = 1*1024 * 1024; //每片文件大小data = this.data;//var files = obj.pushFile();updateobj=obj;obj.preview(function (index, file, result) {getmd5(file,fileShardSize).then(e =>{switchC=false;fileShardIndex=1;//分片索引fileY=file;fileKey=e;fileSize=file.size;fileShardTotal=Math.ceil(file.size/fileShardSize);//分片总数fileName=file.name;fileSuffix = fileName.substr(fileName.lastIndexOf('.') + 1);fileName = fileName.substr(0, fileName.lastIndexOf('.'));data.fileName = fileName;data.fileShardTotal=fileShardTotal;data.fileKey=fileKey;data.fileSuffix=fileSuffix;data.fileShardSize=fileShardSize;data.fileSize=fileSize;element.progress('uploadProgress', fileShardIndex*10+'%');$('.loading').show();$.ajax({type:"post",data: {"shardKey":fileKey},url:"/checkFile",success:function(res){if(res.code==200){//新文件start=(fileShardIndex-1)*fileShardSize;end =Math.min(file.size,start+fileShardSize);fileShard=file.slice(start,end);//从文件中获取当前分片数据}else if(res.code==220){fileShardIndex=res.ShardIndex;//有上传未完成的start=(fileShardIndex-1)*fileShardSize;end =Math.min(file.size,start+fileShardSize);fileShard=file.slice(start,end);//从文件中获取当前分片数据}else if (res.code==240){//急速上传element.progress('uploadProgress', '100%');// shardIndex=res.ShardIndex;switchC=true;$('.loading').show();setTimeout(function (){alert("极速上传成功");$('.loading').hide();},1000);var div ='<video id="mp4s" controls="controls" autobuffer="autobuffer" autoplay="autoplay" loop="loop">\n' +' <source src='+res.src+' type="video/mp4"></source>\n' +'</video>';$("#mm").append(div);$("#mp4s").css({"width":"352px","height":"200px","margin-left":"120px","margin-top":"150px"});}//读取base64strlet fileReader = new FileReader();fileReader.onload=function (e){let base64str=e.target.result;data.base64=base64str;data.fileShardIndex=fileShardIndex;if(switchC==false){obj.upload(data.base64,data.fileName,data.fileKey,data.fileShardTotal,data.fileShardIndex,data.fileSuffix,data.fileSize,data.fileShardSize);}}fileReader.readAsDataURL(fileShard);}});})});},done: function (res) {if(res.code==200){if(res.shardIndex<fileShardTotal){fileShardIndex=fileShardIndex+1;start=(fileShardIndex-1)*fileShardSize;end =Math.min(fileY.size,start+fileShardSize);fileSize=fileY.size;data.fileShardIndex=fileShardIndex;var fileShardtem=fileY.slice(start,end);//从文件中获取当前分片数据let fileReader = new FileReader();fileReader.onload = function (e) {let base64str = e.target.result;data.base64=base64str;updateobj.upload(data.base64,fileName,fileKey,fileShardTotal,data.fileShardIndex,fileSuffix,fileSize,fileShardSize);}fileReader.readAsDataURL(fileShardtem);element.progress('uploadProgress', Math.ceil(fileShardIndex * 100 / fileShardTotal) + '%');}}else if(res.code==100){var div ='<video id="mp4s" controls="controls" autobuffer="autobuffer" autoplay="autoplay" loop="loop">\n' +' <source src='+res.src+' type="video/mp4"></source>\n' +'</video>';$("#mm").append(div);$("#mp4s").css({"width":"352px","height":"200px","margin-left":"120px","margin-top":"150px"});setTimeout(function (){alert("上传完成");$("#mp4s").attr("src",res.src);$('.loading').hide();},1000)}}});});</script></html>

后端代码

package com.xk.controller;import com.xk.entity.FileUpdate;import com.xk.service.IFileUpdateService;import com.xk.utils.Base64ToFile;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile;import java.io.*;import java.util.HashMap;import java.util.Map;/*** <p>* 前端控制器* </p>** @author xk柠檬* @since -12-17*/@Controllerpublic class FileUpdateController {@AutowiredIFileUpdateService iFileUpdateService;@RequestMapping(value = "/bigupdate",method = RequestMethod.POST)@ResponseBodypublic Map<String,Object> upload(FileUpdate fileUpdate) throws Exception {Map<String,Object> map = new HashMap<String, Object>() ;//base64转文件MultipartFile multipartFile = Base64ToFile.Base64ToFilepart(fileUpdate.getBase64());//实际存储路径String path ="F:\\updateTest\\"+fileUpdate.getFileKey()+"."+fileUpdate.getFileShardIndex();multipartFile.transferTo(new File(path));//插入逻辑地址 MvcConfig.class中做了一个路径映射fileUpdate.setFilePath("/Path/"+fileUpdate.getFileKey());iFileUpdateService.selectWhereKeyUpdate(fileUpdate);//判断当前分片是否为最后一个if(fileUpdate.getFileShardIndex().equals(fileUpdate.getFileShardTotal())){map.put("code",100);map.put("src",fileUpdate.getFilePath()+"."+fileUpdate.getFileSuffix());fileUpdate.setFilePath("F:\\updateTest\\"+fileUpdate.getFileKey());//合并分片merge(fileUpdate);return map;}else{map.put("code",200);map.put("shardIndex",fileUpdate.getFileShardIndex());}return map;}@RequestMapping("/checkFile")@ResponseBodypublic Map<String,Object> checkFile(@RequestParam String shardKey){Map<String,Object> map = new HashMap<String, Object>();FileUpdate fileUpdate = iFileUpdateService.selectWhereKey(shardKey);if(fileUpdate==null){//新的文件map.put("code",200);}else if(fileUpdate!=null){if(fileUpdate.getFileShardIndex()<fileUpdate.getFileShardTotal()){map.put("code",220);map.put("ShardIndex",fileUpdate.getFileShardIndex()+1);}else if(fileUpdate.getFileShardIndex()==fileUpdate.getFileShardTotal()){map.put("code",240);map.put("src",fileUpdate.getFilePath()+"."+fileUpdate.getFileSuffix());}}return map;}/*@GetMapping("/GetInfo")public FileUpdate GetInfo(){FileUpdate byId = iFileUpdateService.getById(1);return byId;}*/@GetMapping("/")public String gouindex(){System.out.println("去首页");return "index";}//@RequestMapping("merge")public void merge(FileUpdate fileUpdate) throws Exception {Map<String,Object> map = new HashMap<String, Object>();//输出文件File newfile = new File(fileUpdate.getFilePath()+"."+fileUpdate.getFileSuffix());//文件追加FileOutputStream outputStream =new FileOutputStream(newfile,true);//分片文件FileInputStream fileInputStream=null;byte[] byt=new byte[10*1024*1024];int len;try {for (int i =0;i<fileUpdate.getFileShardTotal();i++){fileInputStream=new FileInputStream(new File(fileUpdate.getFilePath()+"."+(i+1)));while ((len=fileInputStream.read(byt))!=-1){outputStream.write(byt,0,len);}}}catch(IOException e){System.out.println("合并异常"+e.toString());}finally {try{if(fileInputStream!=null){fileInputStream.close();}outputStream.close();System.out.println("IO关闭成功");}catch (Exception e){System.out.println("IO关闭异常"+e);}}System.gc();Thread.sleep(100);//删除分片for (int i=0;i<fileUpdate.getFileShardTotal();i++){String path=fileUpdate.getFilePath()+"."+(i+1);File file = new File(path);boolean delete = file.delete();}//删除分片结束}}

数据库

CREATE TABLE `file_update` (`file_id` int(11) NOT NULL AUTO_INCREMENT,`file_name` varchar(255) DEFAULT NULL,`file_path` varchar(255) DEFAULT NULL,`file_suffix` varchar(255) DEFAULT NULL,`file_size` varchar(255) DEFAULT NULL,`file_shard_index` int(11) DEFAULT NULL,`file_shard_size` varchar(255) DEFAULT NULL,`file_shard_total` varchar(255) DEFAULT NULL,`file_key` varchar(255) DEFAULT NULL,PRIMARY KEY (`file_id`)) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;

效果展示

测试 分片上传 断点续传 急速秒传 成功没有问题!!页面不好凑活看看

源码 源码我放在码云上了有需要的可以去下载

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。