900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 前端 + 后端 实现分片上传(断点续传/极速秒传)

前端 + 后端 实现分片上传(断点续传/极速秒传)

时间:2024-01-08 18:03:25

相关推荐

前端 + 后端 实现分片上传(断点续传/极速秒传)

先记录下,后面有时间再去实现

可参考链接:vue上传大文件/视频前后端(java)代码

前端 + 后端 实现分片上传(断点续传/极速秒传)

前端slice分片上传,后端用表记录分片索引和分片大小和分片总数,当接受完最后一个分片(分片索引等于分片总数,分片索引从1开始),就合并分片成完成的文件。前端需要递归上传,并显示加载动画和根据分片完成数量显示进度条

临时demo

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><form action="/a"><input type="file" type="hidden" id="file"><!-- 隐藏这个原生的上传文件按钮 --><button type="button" id="btn">触发上传</button></button><!-- 使用它来触发选择图片动作 --></form></body><script src="/ajax/libs/jquery/3.6.1/jquery.js"></script><script>/* 监听选择图片的事件 */document.querySelector('#file').onchange = (e)=>{console.log('改变了');console.log(this); // 这里的this变成了Window, 因为写成了箭头函数。console.dir(e.target); // 选择了一个文件,所以数组只有一个元素console.log(e.target.files); // FileList {0: File, length: 1}console.log(e.target.files[0]); // File {name: 'GIF -4-1 18-14-01.gif', lastModified: 1680344051705, lastModifiedDate: Sat Apr 01 18:14:11 GMT+0800 (中国标准时间), webkitRelativePath: '', size: 242914, …}upload(e.target.files[0])document.querySelector('#file').value = '' // 让下次即使选择同一个文件仍能触发onchange事件}function upload(file) {console.log(file instanceof Blob); // true, 而Blob中有个slice方法,可以对文件进行分片let formData = new FormData()let shardSize = 10 * 1024 * 1024let shardIndex = 1let start = shardSize * shardIndexlet end = Math.min(file.size, start + shardSize)console.log(start,end);formData.append('mfile', file.slice(start,end))// 携带数据请求后台$.ajax({url: 'http://127.0.0.1:8083/article/uploadImg',type: 'POST',data: formData,contentType: false,processData: false,cache: false,success: function (data) {if (data.success) {alert('添加成功');} else {alert('添加失败');}}});}/* 点的是#btn,但是我们要触发#file文件上传 */document.querySelector('#btn').onclick = function(){document.querySelector('#file').click()}</script></html>

@PostMapping("uploadImg")public Result uploadImg(@RequestParam("mfile") MultipartFile mfile) throws IOException {String filename = mfile.getOriginalFilename();mfile.transferTo(new File("D:\\Projects\\vue-springboot\\src\\main\\resources\\static\\img\\"+filename));return Result.ok(filename);}

spring:servlet:multipart:max-file-size: 50MBmax-request-size: 50MB

oss 将前面的分片上传改为oss里的追加上传

public static void main(String[] args) throws IOException {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "https://oss-cn-";// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。String accessKeyId = "xxx";String accessKeySecret = "yyy";// 填写Bucket名称,例如examplebucket。String bucketName = "test-zzhua";String objectName = "video/juc.mp4";OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);ObjectMetadata meta = new ObjectMetadata();meta.setObjectAcl(CannedAccessControlList.PublicRead);RandomAccessFile raFile = new RandomAccessFile(new File("D:\\Projects\\vue-springboot\\src\\main\\resources\\static\\img\\juc.mp4"), "r");long totalLen = raFile.length();// 定义每次追加上传的大小 3Mlong everyLen = 3 * 1024 * 1024;long accLen = 0;byte[] bytes = new byte[5 * 1024]; // 缓冲数组5kwhile (true) {// 找到上次读取的位置raFile.seek(accLen);boolean finish = false;ByteArrayOutputStream baos = new ByteArrayOutputStream();// 当前读取累积3M, 或不够3M就读完了int currLen = 0;while (true) {int readLen = raFile.read(bytes);if (readLen == -1) {finish = true;break;}currLen += readLen;baos.write(bytes, 0, readLen);if (currLen >= everyLen) {break;}}// 发起追加请求ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, objectName, bais,meta);appendObjectRequest.setPosition(accLen);ossClient.appendObject(appendObjectRequest);if (finish) {break;}accLen += currLen;}}

md5大文件计算

javascript实现

参考:SpringBoot大文件上传–前端计算文件的MD5

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="/ajax/libs/spark-md5/3.0.2/spark-md5.js"></script></head><body><form id="from" method="post" action="/upload" enctype="multipart/form-data"><table><tr><td><input id="md5" name="md5"><input id="file" name="upload" type="file"><input id="submit" type="submit" value="上传"></td></tr></table></form></body><script>//注意此方法引用了SparkMD5库 library:/satazor/SparkMD5//监听文本框变化document.getElementById("file").addEventListener("change", function() {//声明必要的变量chunks=0;currentChunk=0;var fileReader = new FileReader();//一个用来读取文件的对象//文件分割方法(注意兼容性)blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice,file = document.getElementById("file").files[0],//文件每块分割2M,计算分割详情chunkSize = 2097152,chunks = Math.ceil(file.size / chunkSize),//文件分成了几块currentChunk = 0,//当前处理的第几块spark = new SparkMD5();//创建md5对象(基于SparkMD5)//每块文件读取完毕之后的处理fileReader.onload = function(e) {console.log("读取文件", currentChunk + 1, "/", chunks);//每块交由sparkMD5进行计算spark.appendBinary(e.target.result);currentChunk++;//如果文件处理完成计算MD5,如果还有分片继续处理if (currentChunk < chunks) {loadNext();} else {md5=spark.end();//最终的MD5console.log("MD5:"+md5);}};//处理单片文件的上传function loadNext() {var start = currentChunk * chunkSize,end = start + chunkSize >= file.size ? file.size : start + chunkSize;fileReader.readAsBinaryString(blobSlice.call(file, start, end));//blobSlice.call(file, start, end)每次执行到blobSlice的时候就会跳转到blobSlice定义的地方,可以理解为一个循环}loadNext();});</script></html>

java实现

参考:详解JAVA中获取文件MD5值的四种方法

须引入commons-codec包

String s = DigestUtils.md5Hex(new FileInputStream(new File("D:\\documents\\尚硅谷谷粒学院项目视频教程\\6 - What If I Want to Move Faster.mp4")));ystem.out.println(s);

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