应用办公生活信息教育商业
投稿投诉
商业财经
汽车智能
教育国际
房产环球
信息数码
热点科技
生活手机
晨报新闻
办公软件
科学动态
应用生物
体育时事

前端上传大文件上传如何做断点续传分片上传断点续传

  大文件上传是什么
  不管怎样简单的需求,在量级达到一定层次时,都会变得异常复杂
  文件上传简单,文件变大就复杂
  上传大文件时,以下几个变量会影响我们的用户体验服务器处理数据的能力请求超时网络波动
  上传时间会变长,高频次文件上传失败,失败后又需要重新上传等等
  为了解决上述问题,我们需要对大文件上传单独处理
  这里涉及到分片上传及断点续传两个概念分片上传
  分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(Part)来进行分片上传
  如下图
  上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件
  大致流程如下:将需要上传的文件按照一定的分割规则,分割成相同大小的数据块;初始化一个分片上传任务,返回本次分片上传唯一标识;按照一定的策略(串行或并行)发送各个分片数据块;发送完成后,服务端根据判断数据上传是否完整,如果完整,则进行数据块合成得到原始文件断点续传
  断点续传指的是在下载或上传时,将下载或上传任务人为的划分为几个部分
  每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载。用户可以节省时间,提高速度
  一般实现的方式有两种:服务器端返回,告知从哪开始浏览器端自行处理
  上传过程中将文件在服务器上写为临时文件,等全部写完了(文件上传完),将此临时文件重命名为正式文件即可
  如果中途上传中断过,下次上传的时候根据当前临时文件大小,作为在客户端读取文件的偏移量,从此位置继续读取文件数据块,上传到服务器从此偏移量继续写入文件即可实现思路
  个上传组件,需要具备的功能:需要校验文件格式可以上传任何文件,包括超大的视频文件(切片)上传期间断网后,再次联网可以继续上传(断点续传)要有进度条提示已经上传过同一个文件后,直接上传完成(秒传)
  前后端分工:
  前端:文件格式校验文件切片、md5计算发起检查请求,把当前文件的hash发送给服务端,检查是否有相同hash的文件上传进度计算上传完成后通知后端合并切片
  后端:检查接收到的hash是否有相同的文件,并通知前端当前hash是否有未完成的上传接收切片合并所有切片
  整体思路比较简单,拿到文件,保存文件唯一性标识,切割文件,分段上传,每次上传一段,根据唯一性标识判断文件上传进度,直到文件的全部片段上传完毕
  下面的内容都是伪代码
  读取文件内容:constinputdocument。querySelector(input);input。addEventListener(change,function(){varfilethis。files〔0〕;});
  可以使用md5实现文件的唯一性constmd5codemd5(file);
  然后开始对文件进行分割varreadernewFileReader();reader。readAsArrayBuffer(file);reader。addEventListener(load,function(e){每10M切割一段,这里只做一个切割演示,实际切割需要循环切割,varslicee。target。result。slice(0,1010241024);});
  h5上传一个(一片)constformdatanewFormData();formdata。append(0,slice);这里是有一个坑的,部分设备无法获取文件名称,和文件类型,这个在最后给出解决方案formdata。append(filename,file。filename);varxhrnewXMLHttpRequest();xhr。addEventListener(load,function(){xhr。responseText});xhr。open(POST,);xhr。send(formdata);xhr。addEventListener(progress,updateProgress);xhr。upload。addEventListener(progress,updateProgress);functionupdateProgress(event){if(event。lengthComputable){进度条}}
  这里给出常见的图片和视频的文件类型判断functioncheckFileType(type,file,back){typepngjpgmp4。。。fileinput。changethis。files〔0〕backcallback(boolean)varargsarguments;if(args。length!3){back(0);}vartypeargs〔0〕;type(pngjpg),pngvarfileargs〔1〕;varbacktypeofargs〔2〕function?args〔2〕:function(){};if(file。type){如果系统无法获取文件类型,则读取二进制流,对二进制进行解析文件类型varimgType〔ffd8ff,jpg89504e,png000146674797069736F6D,mp4000186674797033677035,mp400006674797033677035,mp40000667479704D534E56,mp400006674797069736F6D,mp400018667479706D703432,m4v0000667479706D703432,m4v000146674797071742020,mov00006674797071742020,mov00006D6F6F76,mov4F676753002,ogg1A45DFA3,ogg52494646xxxx41564920,avi(RIFFfileSizefileTypeLIST)(52494646,DC6C5709,41564920,4C495354)〕;vartypeName〔jpg,png,mp4,mp4,mp4,mp4,mp4,m4v,m4v,mov,mov,mov,ogg,ogg,avi,〕;varsliceSizepngjpgjpeg。test(type)?3:12;varreadernewFileReader();reader。readAsArrayBuffer(file);reader。addEventListener(load,function(e){varslicee。target。result。slice(0,sliceSize);readernull;if(sliceslice。byteLengthsliceSize){varviewnewUint8Array(slice);vararr〔〕;view。forEach(function(v){arr。push(v。toString(16));});viewnull;varidxarr。join()。indexOf(imgType);if(idx1){back(typeName〔idx〕);}else{arrarr。map(function(v){if(i3i8){returnx;}returnv;});varidxarr。join()。indexOf(imgType);if(idx1){back(typeName〔idx〕);}else{back(false);}}}else{back(false);}});}else{vartypefile。name。match(。(w))〔1〕;back(type);}}
  调用方法如下checkFileType((movmp4avi),file,function(fileType){fileTypemp4,如果file的类型不在枚举之列,则返回false});
  上面上传文件的一步,可以改成:formdata。append(filename,md5code。fileType);
  有了切割上传后,也就有了文件唯一标识信息,断点续传变成了后台的一个小小的逻辑判断
  后端主要做的内容为:根据前端传给后台的md5值,到服务器磁盘查找是否有之前未完成的文件合并信息(也就是未完成的半成品文件切片),取到之后根据上传切片的数量,返回数据告诉前端开始从第几节上传
  如果想要暂停切片的上传,可以使用XMLHttpRequest的abort方法代码!DOCTYPEhtmlhtmllangenheadmetacharsetUTF8metanameviewportcontentwidthdevicewidth,initialscale1。0metahttpequivXUACompatiblecontentieedgetitle文件上传titlestyle自定义进度条样式。precentinput〔typerange〕{webkitappearance:none;清除系统默认样式width:7。8rem;background:webkitlineargradient(ddd,ddd)norepeat,ddd;设置左边颜色为61bd12,右边颜色为dddbackgroundsize:75100;设置左右宽度比例height:0。6rem;横条的高度borderradius:0。4rem;border:1pxsolidddd;boxshadow:0010pxrgba(0,0,0,。125)inset;}拖动块的样式。precentinput〔typerange〕::webkitsliderthumb{webkitappearance:none;清除系统默认样式height:。9rem;拖动块高度width:。9rem;拖动块宽度background:fff;拖动块背景borderradius:50;外观设置为圆形border:solid1pxddd;设置边框}styleheadbodyh1大文件分片上传测试h1inputidfiletypefilenameavatarinputidsubmitBtntypebuttonvalue提交inputidpauseBtntypebuttonvalue暂停inputtyperangevalue0spanidprecentVal0spanbodyhtml
  大文件分片上传处理(document)。ready((){constsubmitBtn(submitBtn);提交按钮constprecentDom(。precentinput)〔0〕;进度条constprecentVal(precentVal);进度条值对应domconstpauseBtn(pauseBtn);暂停按钮每个chunk的大小,设置为1兆constchunkSize110241024;获取slice方法,做兼容处理constblobSliceFile。prototype。sliceFile。prototype。mozSliceFile。prototype。webkitSlice;对文件进行MD5加密(文件内容文件标题形式)consthashFile(file){returnnewPromise((resolve,reject){constchunksMath。ceil(file。sizechunkSize);letcurrentChunk0;constsparknewSparkMD5。ArrayBuffer();constfileReadernewFileReader();functionloadNext(){conststartcurrentChunkchunkSize;constendstartchunkSizefile。size?file。size:startchunkSize;fileReader。readAsArrayBuffer(blobSlice。call(file,start,end));}fileReader。onloade{spark。append(e。target。result);AppendarraybuffercurrentChunk1;if(currentChunkchunks){loadNext();}else{console。log(finishedloading);constresultspark。end();通过内容和文件名称进行md5加密constsparkMd5newSparkMD5();sparkMd5。append(result);sparkMd5。append(file。name);consthexHashsparkMd5。end();resolve(hexHash);}};fileReader。onerror(){console。warn(文件读取失败!);};loadNext();})。catch(err{console。log(err);});}提交submitBtn。on(click,async(){varpauseStatusfalse;varnowUploadNums01。读取文件constfileDom(file)〔0〕;constfilesfileDom。files;constfilefiles〔0〕;if(!file){alert(没有获取文件);return;}2。设置分片参数属性、获取文件MD5值consthashawaithashFile(file);文件hashconstblockCountMath。ceil(file。sizechunkSize);分片总数constaxiosPromiseArray〔〕;axiosPromise数组文件上传constuploadFile(){conststartnowUploadNumschunkSize;constendMath。min(file。size,startchunkSize);构建表单constformnewFormData();blobSlice。call(file,start,end)方法是用于进行文件分片form。append(file,blobSlice。call(file,start,end));form。append(index,nowUploadNums);form。append(hash,hash);ajax提交分片,此时contenttype为multipartformdataconstaxiosOptions{onUploadProgress:e{nowUploadNums;判断分片是否上传完成if(nowUploadNumsblockCount){setPrecent(nowUploadNums,blockCount);uploadFile(nowUploadNums)}else{4。所有分片上传后,请求合并分片文件axios。all(axiosPromiseArray)。then((){setPrecent(blockCount,blockCount);全部上传完成axios。post(filemergechunks,{name:file。name,total:blockCount,hash})。then(res{console。log(res。data,file);pauseStatusfalse;alert(上传成功);})。catch(err{console。log(err);});});}},};加入到Promise数组中if(!pauseStatus){axiosPromiseArray。push(axios。post(fileupload,form,axiosOptions));}}设置进度条functionsetPrecent(now,total){varprencentValue((nowtotal)100)。toFixed(2)precentDom。valueprencentValueprecentVal。text(prencentValue)precentDom。style。cssTextbackground:webkitlineargradient(top,059CFA,059CFA)00{prencentValue}100norepeat}暂停pauseBtn。on(click,(e){pauseStatus!pauseStatus;e。currentTarget。valuepauseStatus?开始:暂停if(!pauseStatus){uploadFile(nowUploadNums)}})uploadFile();});})
  文件上传和合并分片文件接口(node)constRouterrequire(koarouter);constmulterrequire(koamulter);constfsrequire(fsextra);constpathrequire(path);constrouternewRouter();const{mkdirsSync}require(。。utilsdir);constuploadPathpath。join(dirname,upload);constchunkUploadPathpath。join(uploadPath,temp);constuploadmulter({dest:chunkUploadPath});文件上传接口router。post(fileupload,upload。single(file),async(ctx,next){const{index,hash}ctx。req。body;constchunksPathpath。join(chunkUploadPath,hash,);if(!fs。existsSync(chunksPath))mkdirsSync(chunksPath);fs。renameSync(ctx。req。file。path,chunksPathhashindex);ctx。status200;ctx。res。end(Success);})合并分片文件接口router。post(filemergechunks,async(ctx,next){const{name,total,hash}ctx。request。body;constchunksPathpath。join(chunkUploadPath,hash,);constfilePathpath。join(uploadPath,name);读取所有的chunksconstchunksfs。readdirSync(chunksPath);创建存储文件fs。writeFileSync(filePath,);if(chunks。length!totalchunks。length0){ctx。status200;ctx。res。end(切片文件数量不符合);return;}for(leti0;itotal;i){追加写入到文件中fs。appendFileSync(filePath,fs。readFileSync(chunksPathhashi));删除本次使用的chunkfs。unlinkSync(chunksPathhashi);}fs。rmdirSync(chunksPath);文件合并成功,可以把文件信息进行入库。ctx。status200;ctx。res。end(Success);})使用场景大文件加速上传:当文件大小超过预期大小时,使用分片上传可实现并行上传多个Part,以加快上传速度网络环境较差:建议使用分片上传。当出现上传失败的时候,仅需重传失败的Part流式上传:可以在需要上传的文件大小还不确定的情况下开始上传。这种场景在视频监控等行业应用中比较常见小结
  当前的伪代码,只是提供一个简单的思路,想要把事情做到极致,我们还需要考虑到更多场景,比如切片上传失败怎么办上传过程中刷新页面怎么办如何进行并行上传切片什么时候按数量切,什么时候按大小切如何结合WebWorker处理大文件上传如何实现秒传
  人生又何尝不是如此,极致的人生体验有无限可能,越是后面才发现越是精彩
  给大家分享我收集整理的各种学习资料,前端小白交学习流程,入门教程等回答下面是学习资料参考。
  前端学习交流、自学、学习资料等推荐知乎

牛仔裤衬衫不费力的时髦感,不愧是春季高颜值穿搭春季高颜值穿搭:牛仔裤衬衫,不过时的经典CP!牛仔裤和衬衫都是我们衣橱里的基础单品,由于属于不同风格,一个休闲一个通勤,大家很少把它们放在一起搭配。然而看过时尚杂志和街拍……建议中年人如果不差钱,这2种茶能不喝就不喝,难喝不说还伤身茶是我们的国饮,至今已经有数千年的历史,尤其古代的文人墨客喜欢以茶代酒,吟诗作赋。历史上,对茶最痴迷的人恐怕非茶圣陆羽莫属,除此之外,还有一位则是被称之为茶痴的唐代著名诗人卢仝……假球失人心!上海球市惨淡,媒体爆料篮协取消苏沪本赛季成绩北京时间4月16日,距离CBA八强赛开赛剩下不到一天的时间。在此之前,上海男篮和江苏男篮疑似打假球冲上热搜,在舆论的压力下,篮协成立公司对本事件展开调查。根据上海男篮公开……傍晚时分的街头时尚灯光下的魅力少女这是AI绘画街拍系列的第二作,这次的主题依旧是傍晚时分的街头时尚。在傍晚时分,城市的街道上总是有许多时尚的女孩穿着夹克和牛仔裤,在人群中穿行。这样的场景在街头随处可见。在……个人面临的最大困境,是选择困难症对我们每个人来说,个人面临的最大困境,是选择困难症。这是一件常见的事情,通常会伴随我们一生,即使有正确的智慧,加上长时间的努力,修行,最多也只能做到缓解,而无法彻底解决。……大家给说说,孩子需要上幼小衔接吗?孩子6岁了,今年下半年就要开启小学生活,在上不上幼小衔接一直是我们纠结的点。自从国家开始给教育减负之后,打压了很多课外培训机构,并且出台了一系列鼓励幼儿园开办幼小衔接的政……买卖房屋找中介别慌避坑有法日前,一度炒得沸沸扬扬的明星张杰、谢娜夫妇买房跳单事件,有了最新进展,法院一审判决认定谢娜、张杰购房不存在跳单行为。目前通过中介机构进行房屋买卖,已经成为二手房交易的主要……没有5位数,别想走出董洁的直播间!要说今年翻红最成功的明星,那一定非董洁莫属。谁也没想到,她会以直播带货的方式再次翻红,更出乎意料的是,这次嘲讽的声音屈指可数。自从上个月宣布跟潘粤明世纪大和解,如今……澳门赛今日看点孙颖莎迎首战,陈梦再战石川佳纯(附赛程)WTT澳门冠军赛,随着比赛的进行,如今已经到了第三个比赛日。在第二个比赛日,国乒的表现有喜有忧,在第一轮比赛中,女乒方面,世界冠军陈幸同意外出局,爆出了开赛以来的最大冷门……韵达快递派送包裹一周未送达,顾客投诉无果接到疑似快递员上门报封面新闻记者喻言韵达快递员辱骂客户,派送延迟还拒绝送到收货地点附近,甚至向中通快递员骗取我的地址试图上门报复近日,山西太原的张女士向封面新闻投诉称,自己在网上下单,经由韵……韩国旅游业急招人手迎接中国游客还推出花式促销来源:海外网资料图:韩国空乘人员在机舱表演节目海外网3月15日电韩国《济民日报》3月13日发文称,韩国济州岛将增加韩中航班,并重启邮轮旅游。为迎接中国游客的到来,当地旅游……拼多多平台如何管控价格?(电商控价怎么做)随着电商的高速发展,电商平台的竞争日益激烈,与此同时,电商平台的价格竞争也日益激烈,低价乱价现象也随之增多。而拼多多平台因其定位以及受众群体更偏向下沉市场,因此相对来说拼多多平……
有一种旅行,叫冬天去云南头条创作挑战赛11月,北风卷地,树木凋零中国的大部分地方,都已是冬景萧瑟唯有云南,像是打翻了上帝的调色盘依旧美得绚丽又多彩图源Chen图源陈……山东男篮新外确定,边强赴美考察莫兰德,三人篮球公布集训名单山东男篮相关消息:根据山东资深体育记者夏晓司老师发布的消息称山东男篮新外援基本确定人选,并不是之前网络上爆出的西蒙斯。同时在与球迷评论中夏晓司老师也否定了新外援是威尔斯的……另类春游《我们一家人》,从《家乡》出发,经过《鱼米之乡》,来到了《春城》,看到了《春光美》。人们迎着《春天的阳光》,讲着《春天的故事》,跳着《春天的芭蕾》,唱着《春之歌》,采着《春茶》……肝脏最怕四件事,养肝多做三个疏肝动作无论男女,都需要养肝。肝在五行属木,具有树木生生不息、伸展调达、升发旺盛的特点,与春气相通应,因此春季养生要格外关注肝气的舒展。春天应该怎么养肝护肝呢?首先,肝最怕的四件事不要……出境团队游价格上浮背后海外供应链需重建,不少接团的中餐厅都关2023年2月8日,杭州,前往印尼巴厘岛的旅行团的旅客在萧山国际机场T4航站楼准备通过国际、港澳台的安检通道。视觉中国图随着2月6日出境团队游试点恢复,多个省市出境游首团……生态泳池满载着乡土气息与儿时回忆,休闲农业必备导读开展休闲农业与乡村旅游,常见的亲水体验项目有泡温泉、垂钓、抓鱼、泥塘游戏等等,只是炎炎夏日里不能游泳多少有些遗憾。乡村的生态泳池传统的酒店泳池、场馆泳池毕……ChatGPT问答测试(第一期)2023年2月14日2023年2月14日Q:玛雅预言,2012年地球毁灭,为什么没有实现?A:玛雅预言并不说地球会在2012年毁灭,而是有关于2012年会发生一个重要的历史转折点,但是……立春时节抓住一年中疏肝解郁最好的15天立春至,万物生,作为二十四节气中的第一个节气,也意味着新的一年正式开始,正所谓阳和起蛰,品物皆春,过了立春,万物复苏,一片欣欣向荣的,一年四季也正式拉开序幕。时至立春,白……生育登记取消结婚限制?官方回应近日,四川省卫健委发布通知显示,新版《四川省生育登记服务管理办法》(简称新《办法》),将于2023年2月15日起施行。根据规定,新《办法》适用于双方或一方为四川省户籍人口,以及……聊聊17岁的老伙计jQuery在2022年过的如何?大家好,很高兴又见面了,我是前端进阶,由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!17岁的jQuery消失在2023年……焦点访谈激情冰雪热中国央视网消息(焦点访谈):一年前,北京鸟巢中燃起的一簇微火照耀天地,北京冬奥会这一相约七年的冰雪盛会展开了精彩画卷。而在这个北京冬奥后的第一个冰雪季,冰雪运动成为越来越多中国人冬……阿森纳一战,英超喜获世界最佳!肱骨之臣非阿尔特塔,温格欣慰阿森纳42两度追平并逆转取胜维拉一役,堪称本赛季阿森纳乃至英超的经典之战,整场比赛让枪迷就像坐了过山车一样,心情经历了绝望到狂喜。在这场比赛前,阿森纳已经各项赛事4场不胜,经历……
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网