Vue.Js及Java實(shí)現(xiàn)文件分片上傳代碼實(shí)例
說(shuō)明
代碼從項(xiàng)目中剝離修改,未經(jīng)測(cè)試,僅提供思路。
前端
upload(file) { //從后臺(tái)獲取已經(jīng)上傳的文件分片數(shù) getIdx(md5) .then(function(res) { let retry = 3; uploadPart(retry, file, res.data); }) .catch(); } uploadPart(retry, file, idx) { //設(shè)置分片大?。▎挝籅yte) let bufferLength = 1024 * 1024 * 5; //計(jì)算開(kāi)始的切割點(diǎn),idx是上傳成功的分片數(shù),未上傳過(guò)文件則開(kāi)始點(diǎn)為0 let start = idx * bufferLength; //全部上傳完畢或重試次數(shù)用完則退出 if(start>=file.size || retry<=0) return; //計(jì)算分割的位置 let end = start + bufferLength; //如果分割點(diǎn)超出文件大小,回退分割點(diǎn) if (end > file.size) {end = fileSize;} //切割文件 var chunk = file.slice(start, end); //創(chuàng)建 formData 對(duì)象并添加數(shù)據(jù) let formData = new FormData(); formData.set("file", chunk); //如果是第一次上傳,連同文件塊數(shù)量也上傳 if (start == 0) { //計(jì)算文件切片總數(shù),向上取整 let chunkNum = Math.ceil(file.size / bufferLength); formData.set("total", chunkNum); } //上傳文件的api,此處使用axios發(fā)送請(qǐng)求 doUpload(formData) //發(fā)送成功,則上傳下一片,遞歸調(diào)用方法 .then(function() { retry = xx;//刷新重試次數(shù) uploadPart(retry, file, ++idx); }) //發(fā)送失敗 .catch(function() { retry--;//重試次數(shù)減一 //重試上傳這一片 uploadPart(retry, file, idx); }); },
文件分片上傳的前端關(guān)鍵代碼只有一句:
//切割文件
var chunk = file.slice(start, end);
通過(guò)slice方法來(lái)切割文件,然后文件上傳的流程視業(yè)務(wù)和具體技術(shù)而定,此處是使用axios發(fā)送請(qǐng)求,用遞歸調(diào)用上傳文件塊。
需要注意的是,Blob.slice(start, end),文件塊包含start指向的字節(jié),而不包含end指向的字節(jié),在使用時(shí)要注意Blob的邊界。
mozilla對(duì)slice的說(shuō)明
后端
/**合并文件的實(shí)際操作*/ public static void doMergeFiles(String outFile, String[] files) { //設(shè)置緩存大小 int BUFSIZE = 1024 * 1024; //排序。文件后綴名是文件的順序。 Arrays.sort(files); //輸出流 FileChannel outChannel = null; //標(biāo)記最后的一個(gè)文件 String lastFlag = files[files.length-1]; try { outChannel = new FileOutputStream(outFile).getChannel(); //遍歷文件列表 for(String f : files){ //最后一塊文件用真實(shí)大小設(shè)置緩存,避免自動(dòng)填充數(shù)據(jù)造成的md5不一致 if(lastFlag.equals(f)){ File last = new File(f); BUFSIZE = (int) last.length();//獲取文件的大小并設(shè)置成緩存的大小 } FileChannel fc = new FileInputStream(f).getChannel(); //用ByteBuffer創(chuàng)建緩存 ByteBuffer bb = ByteBuffer.allocate(BUFSIZE); while(fc.read(bb) != -1){//把數(shù)據(jù)讀到緩存 bb.flip();//重置游標(biāo) outChannel.write(bb);//寫(xiě)入數(shù)據(jù) bb.clear();//清空數(shù)據(jù) } fc.close();//關(guān)閉流 } } catch (IOException ioe) { ioe.printStackTrace(); } finally { try {if (outChannel != null) {outChannel.close();}} catch (IOException ignore) {} } }
后端的關(guān)鍵是合并文件,當(dāng)上傳完最后一塊文件就進(jìn)行文件的合并。使用ByteBuffer緩存,使用FileChannel進(jìn)行文件的讀寫(xiě)完成合并操作。在保存文件時(shí),文件名取一致,文件的后綴名則取文件塊的順序,比如第一塊文件是“xxx.01”,第10塊是“xxx.10”,注意,個(gè)位數(shù)前面要補(bǔ)“0”,這樣可以直接用Array.sort()進(jìn)行排序。
為提高性能,可以適當(dāng)設(shè)置緩存大小,可以邊上傳文件邊合并,不必等到文件都上傳了才合并。
拓展
此處的文件上傳是一次上傳一片,上傳成功才開(kāi)始上傳下一片。如果前端不是使用javascript,能開(kāi)啟使用多線程的話,可以改成同時(shí)上傳多片文件提高上傳速度。已經(jīng)上傳的文件分片用bitmap存儲(chǔ),上傳文件前,從后臺(tái)獲取已上傳的文件分片的bitmap數(shù)據(jù)然后解析,多線程處理未上傳的文件分片。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue2.0結(jié)合webuploader實(shí)現(xiàn)文件分片上傳功能
- vue實(shí)現(xiàn)大文件分片上傳與斷點(diǎn)續(xù)傳到七牛云
- 使用Vue3+ElementPlus前端實(shí)現(xiàn)分片上傳的全過(guò)程
- 利用Vue3+Element-plus實(shí)現(xiàn)大文件分片上傳組件
- vue大文件分片上傳之simple-uploader.js的使用
- Java實(shí)現(xiàn)大文件的分片上傳與下載(springboot+vue3)
- vue3+element 分片上傳與分片下載功能實(shí)現(xiàn)方法詳解
- Vue3利用組合式函數(shù)和Shared Worker實(shí)現(xiàn)后臺(tái)分片上傳
- vue分片上傳視頻并轉(zhuǎn)換為m3u8文件播放的實(shí)現(xiàn)示例
相關(guān)文章
Java并發(fā)多線程編程之CountDownLatch的用法
這篇文章主要介紹了Java并發(fā)多線程編程之CountDownLatch的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Spring6.x對(duì)調(diào)度和異步執(zhí)行的注解支持示例詳解
這篇文章主要為大家介紹了Spring6.x對(duì)調(diào)度和異步執(zhí)行的注解支持示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11Java數(shù)組操作經(jīng)典例題大總結(jié)
數(shù)組是在內(nèi)存中存儲(chǔ)相同數(shù)據(jù)類型的連續(xù)的空間,聲明一個(gè)數(shù)組就是在內(nèi)存空間中劃出一串連續(xù)的空間,下面這篇文章主要給大家介紹了關(guān)于Java數(shù)組操作經(jīng)典例題的相關(guān)資料,需要的朋友可以參考下2022-03-03IntelliJ IDEA編譯項(xiàng)目報(bào)錯(cuò) "xxx包不存在" 或 "找不到符號(hào)"
這篇文章主要介紹了IntelliJ IDEA編譯項(xiàng)目報(bào)錯(cuò) "xxx包不存在" 或 "找不到符號(hào)" ,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08