博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HTML5 大文件断点续传完整思路整理
阅读量:6226 次
发布时间:2019-06-21

本文共 4172 字,大约阅读时间需要 13 分钟。

利用 html5 的新特性分割文件,为达到断点续传功能

spark.js 获取文件md5以确保文件的唯一性

流程概述:

(此功能前端共需调用3个接口,分别为简称作 A / B / C)  1,获取文件信息:使用HTML5的原生上传input,选择文件后,获取文件的所有信息(文件名、文件总字节数等)  2,计算总切片:跟后台约定好单个切片大小,比如1M/片,计算文件总大小/单个切片大小=总切片数  3,计算文件MD5和每个切片的MD5:引用spark-md5.min.js来生成MD5,此js的调用可以获取文件MD5、切片的MD5和切片的数据  4,调用A接口查询从第几个切片开始上传:需要向后台传入的关键参数是文件名、文件总大小、文件的MD5  5,获取到初始上传切片位置,正式开始分片上传到服务器:从A接口获取到切片位置后,调用接口B,将切片的MD5和切片数据传给后台,此后循环调用接口B,直到最后一切片上传结束  6,所有切片上传结束后,调用接口C将文件存库复制代码

详细代码展示:

HTML:

复制代码

获取文件信息:

function handleFile() {     var fileInputs = $("input[name='myfiles']")[0]; //获取input里的文件信息     //切割文件的每条内容分别存放     var name = fileInputs.files[0].name, //文件名                    size = fileInputs.files[0].size, //文件总字节          type = fileInputs.files[0].type, //文件类型 (此功能暂且用不到)         shardSize = 1024 * 1024, // 每个切片的总字节数,比如此时以1M为一个分片         shardCount = Math.ceil(size / shardSize); //总片数}复制代码

计算整个文件的MD5:(前提是引入了spark.js,下载地址: )

var singleFileData = new Array(); //初始空数组,储存所有的切片数据var fileReader = new FileReader(),   blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice,   chunkSize = shardSize , //单个切片的总字节数   chunks = shardCount, //总片数   currentChunk = 0;var spark = new SparkMD5.ArrayBuffer();    fileReader.onload = function (e) {    //*******获取分片文件,用于计算所有切片的MD5***       for (var i = 0; i < chunks; i++) {         var start = i * chunkSize,         end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;         var sliceFile = blobSlice.call(file, start, end);         // 调用此方法,计算每个切片的MD5          getChunkMd5(sliceFile, i);         }    //*****************************    spark.append(e.target.result);    if (currentChunk < chunks) {       currentChunk++;       loadNext();    } else {      var allFileEnd = spark.end()       console.log("此值为整个切片的MD5", allFileEnd)       //真实MD5值 :allFileEnd=a0ce27800ee7d948422f3fe16e898f22       // ***调用接口(1),查询从第几个切片开始上传***       // ***在此处写接口A的调用方法***     }    }; function loadNext() {  //计算切片的start,end,用于切割出切片的数据  var start = currentChunk * chunkSize,  end = start + chunkSize >= file.size ? file.size : start + chunkSize;  fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));   //储存切片的数据   //判断如果singleFileData小于总切片数,则继续往数组添加切片数据   if (singleFileData.length != chunks) {    singleFileData.push(blobSlice.call(file, start, end)) //将每个切片push到空数组里   }  };  //调用此方法,循环获取切片数据  loadNext()复制代码

计算切片的MD5:

(此步骤其实可以省略,但为了严谨后端需要根据前端传入的切片数据计算出MD5,跟前端传入的MD5对比)
var mySingleFileMd5 = []; //用于储存所有切片的MD5    function getChunkMd5(file, i) {       var spark = new SparkMD5.ArrayBuffer();       var fileReader = new FileReader();       fileReader.onload = function (e) {         spark.append(e.target.result);         mySingleFileMd5[i] = spark.end();// 将每个切片的MD5存起来         console.log("所有切片的MD5数组=", mySingleFileMd5);       }       fileReader.onerror = function () {         console.warn('oops, something went wrong');       }       function loadNext() {         fileReader.readAsArrayBuffer(blobSlice.call(file, 0, file.size));       }   loadNext();  }复制代码

调用接口A后获取到 PARTINDEX(从第几个切片开始上传),接着调用接口B进行上传,上传后手动计算进度。

A接口传参、取参如下:

var params = {          serviceid: 'wcm61_bigfile',          methodname: 'startUpload',          fileName: 手机QQ视频_20181212094958.mp4,          fileDigest:  65309fc9684b4eb2f3d281da5ad17b6e,          fileSize: 100904886,        };{    "MSG":"操作成功",    "DATA":{        "TOTALPARTCOUNT":"49",        "PARTINDEX":"1",  //此字段就是后台告诉前端从第几个切片开始上传        "PARTSIZE":"2097152",        "FLAG":"1",        "FILENAME":"手机QQ视频_20181212094958.mp4"     },    "ISSUCCESS":"true"}复制代码

B接口传参、取参如下:

var data = singleFileData[partIndex - 1] //切片数据  var fileName =手机QQ视频_20181212094958.mp4; //文件名  var fileDigest = 65309fc9684b4eb2f3d281da5ad17b6e; //文件的MD5  var partIndex = 1; //切片位置  var partDigest = ea58e21870ad4c22f2c75645564654b2; //切片的MD5{    "filename":"手机QQ视频_20181212094958.mp4",    "PARTINDEX":"2",  //下次开始传第2个切片    "PARTSIZE":"2097152", //切片大小    "totalPartCount":"49" //总切片数    "ISSUCCESS":"1"}复制代码

通过B接口,不断将切片上传到服务器,并且实时计算上传进度

var processNum =      parseInt((PARTINDEX - 1) / totalPartCount * 100)  // 已上传的切片/总切片数 复制代码

最终实现静态效果和接口如下:

转载于:https://juejin.im/post/5c80cd506fb9a049e702e3c9

你可能感兴趣的文章
LeetCode OJ:Min Stack(最小栈问题)
查看>>
什么是FPGA,PAL,EPLD?
查看>>
OO第一次博客作业
查看>>
计算机发展史简述
查看>>
wpf 遍历控件及其值
查看>>
Unity5.6.4f1 配置WebGL教程
查看>>
linux -硬盘分区
查看>>
Struts1防止重复提交
查看>>
JS控制滚动条的位置
查看>>
来自我的破船大大的博客,记录他的iOS成长之路,与君同勉!
查看>>
GridView 编辑、删除 、分页
查看>>
[洛谷P2742]【模板】二维凸包([USACO5.1]圈奶牛Fencing the Cows)
查看>>
C/C++动态二维数组的内存分配和释放
查看>>
HTC G7 官方ROM卡刷包(国行、台版、港版、印度、亚太版、欧版)
查看>>
jQuery笔记(五)jQuery表单验证
查看>>
编程助手JavaScript学习库-面向对象编程笔记
查看>>
聪明的数据结构和笨拙的逻辑代码
查看>>
php_memcache 缓存 下载-安装-配置-学习
查看>>
Java EE之通过表单上传文件
查看>>
Gnome创建桌面快捷方式
查看>>