一对一直播软件开发,node大文件上传的断点续传
一对一直播软件开发,node大文件上传的断点续传
实现思路
整体思路比较简单,拿到文件,保存文件唯一性标识,切割文件,分段上传,每次上传一段,根据唯一性标识判断文件上传进度,直到文件的全部片段上传完毕。
下面的内容都是伪代码
读取文件内容:
const input = document.querySelector('input'); input.addEventListener('change', function() { var file = this.files[0]; });
可以使用md5实现文件的唯一性:
const md5code = md5(file);
然后开始对文件进行分割:
var reader = new FileReader(); reader.readAsArrayBuffer(file); reader.addEventListener("load", function(e) { //每10M切割一段,这里只做一个切割演示,实际切割需要循环切割, var slice = e.target.result.slice(0, 10*1024*1024); });
h5上传一个(一片):
const formdata = new FormData(); formdata.append('0', slice); //这里是有一个坑的,部分设备无法获取文件名称,和文件类型,这个在最后给出解决方案 formdata.append('filename', file.filename); var xhr = new XMLHttpRequest(); xhr.addEventListener('load', function() { //xhr.responseText }); xhr.open('POST', ''); xhr.send(formdata); xhr.addEventListener('progress', updateProgress); xhr.upload.addEventListener('progress', updateProgress); function updateProgress(event) { if (event.lengthComputable) { //进度条 } }
这里给出常见的图片和视频的文件类型判断:
function checkFileType(type, file, back) { /** * type png jpg mp4 ... * file input.change=> this.files[0] * back callback(boolean) */ var args = arguments; if (args.length != 3) { back(0); } var type = args[0]; // type = '(png|jpg)' , 'png' var file = args[1]; var back = typeof args[2] == 'function' ? args[2] : function() {}; if (file.type == '') { // 如果系统无法获取文件类型,则读取二进制流,对二进制进行解析文件类型 var imgType = [ 'ff d8 ff', //jpg '89 50 4e', //png '0 0 0 14 66 74 79 70 69 73 6F 6D', //mp4 '0 0 0 18 66 74 79 70 33 67 70 35', //mp4 '0 0 0 0 66 74 79 70 33 67 70 35', //mp4 '0 0 0 0 66 74 79 70 4D 53 4E 56', //mp4 '0 0 0 0 66 74 79 70 69 73 6F 6D', //mp4 '0 0 0 18 66 74 79 70 6D 70 34 32', //m4v '0 0 0 0 66 74 79 70 6D 70 34 32', //m4v '0 0 0 14 66 74 79 70 71 74 20 20', //mov '0 0 0 0 66 74 79 70 71 74 20 20', //mov '0 0 0 0 6D 6F 6F 76', //mov '4F 67 67 53 0 02', //ogg '1A 45 DF A3', //ogg '52 49 46 46 x x x x 41 56 49 20', //avi (RIFF fileSize fileType LIST)(52 49 46 46,DC 6C 57 09,41 56 49 20,4C 49 53 54) ]; var typeName = [ 'jpg', 'png', 'mp4', 'mp4', 'mp4', 'mp4', 'mp4', 'm4v', 'm4v', 'mov', 'mov', 'mov', 'ogg', 'ogg', 'avi', ]; var sliceSize = /png|jpg|jpeg/.test(type) ? 3 : 12; var reader = new FileReader(); reader.readAsArrayBuffer(file); reader.addEventListener("load", function(e) { var slice = e.target.result.slice(0, sliceSize); reader = null; if (slice && slice.byteLength == sliceSize) { var view = new Uint8Array(slice); var arr = []; view.forEach(function(v) { arr.push(v.toString(16)); }); view = null; var idx = arr.join(' ').indexOf(imgType); if (idx > -1) { back(typeName[idx]); } else { arr = arr.map(function(v) { if (i > 3 && i < 8) { return 'x'; } return v; }); var idx = arr.join(' ').indexOf(imgType); if (idx > -1) { back(typeName[idx]); } else { back(false); } } } else { back(false); } }); } else { var type = file.name.match(/\.(\w+)$/)[1]; back(type); } }
调用方法如下:
checkFileType('(mov|mp4|avi)',file,function(fileType){ // fileType = mp4, // 如果file的类型不在枚举之列,则返回false });
上面上传文件的一步,可以改成:
formdata.append('filename', md5code+'.'+fileType);
有了切割上传后,也就有了文件唯一标识信息,断点续传变成了后台的一个小小的逻辑判断。
在一对一直播软件开发中,后端主要做的内容为:根据前端传给后台的md5值,到服务器磁盘查找是否有之前未完成的文件合并信息(也就是未完成的半成品文件切片),取到之后根据上传切片的数量,返回数据告诉前端开始从第几节上传。
如果想要暂停切片的上传,可以使用XMLHttpRequest的 abort方法。
以上就是一对一直播软件开发,node大文件上传的断点续传, 更多内容欢迎关注之后的文章