成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

Node.js怎么實現分片上傳?方法介紹

Node怎么實現分片上傳?下面本篇文章給大家介紹一下Node.js實現分片上傳的方法,希望對大家有所幫助!

Node.js怎么實現分片上傳?方法介紹

大文件上傳會消耗大量的時間,而且中途有可能上傳失敗。這時我們需要前端和后端配合來解決這個問題。

解決步驟:

  • 文件分片,減少每次請求消耗的時間,如果某次請求失敗可以單獨上傳,而不是從頭開始

  • 通知服務端合并文件分片

  • 控制并發的請求數量,避免瀏覽器內存溢出

  • 當因為網絡或者其他原因導致某次的請求失敗,我們重新發送請求

文件的分片與合并

在JavaScript中,FIle對象是' Blob '對象的子類,該對象包含一個重要的方法slice,通過該方法我們可以這樣分割二進制文件:

<!DOCTYPE html> <html> <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="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js"></script> </head> <body>     <input type="file" multiple="multiple" id="fileInput" />     <button onclick="SliceUpload()">上傳</button>       <script>         function SliceUpload() {             const file = document.getElementById('fileInput').files[0]             if (!file) return              // 文件分片             let size = 1024 * 50; //50KB 50KB Section size             let fileChunks = [];             let index = 0;        //Section num             for (let cur = 0; cur < file.size; cur += size) {                 fileChunks.push({                     hash: index++,                     chunk: file.slice(cur, cur + size),                 });             }              // 上傳分片             const uploadList = fileChunks.map((item, index) => {                 let formData = new FormData();                 formData.append("filename", file.name);                 formData.append("hash", item.hash);                 formData.append("chunk", item.chunk);                 return axios({                     method: "post",                     url: "/upload",                     data: formData,                 });             });             await Promise.all(uploadList);              // 所有分片上傳完成,通知服務器合并分片             await axios({                 method: "get",                 url: "/merge",                 params: {                     filename: file.name,                 },             });             console.log("Upload to complete");         }     </script> </body> </html>

并發控制

如果文件很大,這樣切分的分片會很多,瀏覽器短時間內就會發起大量的請求,可能會導致內存耗盡,所以要進行并發控制。

這里我們結合Promise.race()方法 控制并發請求的數量,避免瀏覽器內存溢出。

// 加入并發控制 async function SliceUpload() {     const file = document.getElementById('fileInput').files[0]     if (!file) return      // 文件分片     let size = 1024 * 50; //50KB 50KB Section size     let fileChunks = [];     let index = 0;        //Section num     for (let cur = 0; cur < file.size; cur += size) {         fileChunks.push({             hash: index++,             chunk: file.slice(cur, cur + size),         });     }      let pool = []; //Concurrent pool     let max = 3; //Maximum concurrency     for (let i = 0; i < fileChunks.length; i++) {         let item = fileChunks[i];         let formData = new FormData();         formData.append("filename", file.name);         formData.append("hash", item.hash);         formData.append("chunk", item.chunk);          // 上傳分片         let task = axios({             method: "post",             url: "/upload",             data: formData,         });         task.then(() => {         // 從并發池中移除已經完成的請求         let index = pool.findIndex((t) => t === task);             pool.splice(index);         });          // 把請求放入并發池中,如果已經達到最大并發量         pool.push(task);         if (pool.length === max) {             //All requests are requested complete             await Promise.race(pool);         }     }      // 所有分片上傳完成,通知服務器合并分片     await axios({         method: "get",         url: "/merge",         params: {             filename: file.name,         },     });     console.log("Upload to complete"); }

使代碼可復用

function SliceUpload() {     const file = document.getElementById('fileInput').files[0]     if (!file) return      // 文件分片     let size = 1024 * 50; // 分片大小設置     let fileChunks = [];     let index = 0;        // 分片序號     for (let cur = 0; cur < file.size; cur += size) {         fileChunks.push({             hash: index++,             chunk: file.slice(cur, cur + size),         });     }      const uploadFileChunks = async function(list){         if(list.length === 0){             // 所有分片上傳完成,通知如無             await axios({                 method: 'get',                 url: '/merge',                 params: {                     filename: file.name                 }             });             console.log('Upload to complete')             return         }          let pool = []       // 并發池         let max = 3         // 最大并發數         let finish = 0      // 完成數量         let failList = []   // 失敗列表         for(let i=0;i<list.length;i++){             let item = list[i]             let formData = new FormData()             formData.append('filename', file.name)             formData.append('hash', item.hash)             formData.append('chunk', item.chunk)                          let task = axios({                 method: 'post',                 url: '/upload',                 data: formData             })              task.then((data)=>{                 // 從并發池中移除已經完成的請求                 let index = pool.findIndex(t=> t===task)                 pool.splice(index)             }).catch(()=>{                 failList.push(item)             }).finally(()=>{                 finish++                 // 如果有失敗的重新上傳                 if(finish===list.length){                     uploadFileChunks(failList)                 }             })             pool.push(task)             if(pool.length === max){                 await Promise.race(pool)             }         }     }      uploadFileChunks(fileChunks) }

服務端接口實現

const express = require('express') const multiparty = require('multiparty') const fs = require('fs') const path = require('path') const { Buffer } = require('buffer') // file path const STATIC_FILES = path.join(__dirname, './static/files') // Temporary path to upload files const STATIC_TEMPORARY = path.join(__dirname, './static/temporary') const server = express() // Static file hosting server.use(express.static(path.join(__dirname, './dist'))) // Interface for uploading slices server.post('/upload', (req, res) => {     const form = new multiparty.Form();     form.parse(req, function(err, fields, files) {         let filename = fields.filename[0]         let hash = fields.hash[0]         let chunk = files.chunk[0]         let dir = `${STATIC_TEMPORARY}/${filename}`         // console.log(filename, hash, chunk)         try {             if (!fs.existsSync(dir)) fs.mkdirSync(dir)             const buffer = fs.readFileSync(chunk.path)             const ws = fs.createWriteStream(`${dir}/${hash}`)             ws.write(buffer)             ws.close()             res.send(`${filename}-${hash} Section uploaded successfully`)         } catch (error) {             console.error(error)             res.status(500).send(`${filename}-${hash} Section uploading failed`)         }     }) })  //Merged slice interface server.get('/merge', async (req, res) => {     const { filename } = req.query     try {         let len = 0         const bufferList = fs.readdirSync(`${STATIC_TEMPORARY}/${filename}`).map((hash,index) => {             const buffer = fs.readFileSync(`${STATIC_TEMPORARY}/${filename}/${index}`)             len += buffer.length             return buffer         });         //Merge files         const buffer = Buffer.concat(bufferList, len);         const ws = fs.createWriteStream(`${STATIC_FILES}/${filename}`)         ws.write(buffer);         ws.close();         res.send(`Section merge completed`);     } catch (error) {         console.error(error);     } })  server.listen(3000, _ => {     console.log('http://localhost:3000/') })

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
人人妻人人澡人人爽人人精品图片| 欧美乱大交XXXXX性喷潮| 蜜桃国产精品乱码一区二区三区| 蜜臀av夜夜嗨一区二区粉嫩 | 天天躁日日躁狠狠躁一区| 性色AV无码专区亚洲AV毛片子| 亚洲乱码日产精品BD在线| 中文成人无字幕乱码精品区| WWW.一区二区三区在线 || 丁香婷婷在线成人播放视频| 国产午夜福利片1000无码| 精品一区二区三区免费乱码视频| 蜜臀久久99精品久久久久久小说| 人妻无码久久精品| 无人区卡一卡二卡三乱码入口 | 精品亚洲国产成人AV制服| 免费A级毛片18以上观看精品| 人妻色欲AV无码专区精油按摩 | 国精产品一区一区三区| 久久久久亚洲AV综合波多野结衣| 欧美成人片在线观看网站| 色哟哟免费精品网站入口| 亚洲av无码一区二区三区dv| 中国老太奶BBW性姣| 第一次爱的人视频播放完整版| 国内精品久久久人妻中文字幕| 老汉粗大不带套怀孕| 日韩精品无码综合福利网| 亚洲AV永久天码精品天堂DL| 18禁又污又黄又爽的网站不卡| 高清偷自拍亚洲精品三区| 精品亚洲国产成人AV在线小说| 欧美在线视频二区| 亚洲 A V无 码免 费 成| 中文字幕人成乱码熟女免费| 国产CHINESE中国HDXXXX| 久久AV喷吹AV高潮AV欧美| 人妻丰满熟妇AⅤ无码无码区免费| 无码人妻一区二区免费AV| 中国性猛交ⅩXXX免费看| 贵为皇后却被用来犒赏三军 | 亚洲一线产区二线产区区别在哪儿| CHINESE国产HD中国熟女| 国产未成女一区二区三区| 免费观看美女裸体的网站| 乌克兰13一14处A交| 中文在线最新版天堂| 国产精品99久久免费观看| 美丽的熟妇中文字幕| 无码AV中文字幕出轨人妻 | 高H禁伦餐桌上的肉伦NP| 久久精品国产99精品国产202| 日本做受高潮好舒服视频| 亚洲日韩欧美一区二区三区 | 深夜A级毛片免费视频| 影音先锋女人AV女色资源| 国产成人无码18禁午夜福利P| 老熟妇毛茸茸BBW视频| 无码专区狠狠躁躁天天躁| AAA少妇高潮大片免费看| 国内精品久久久久久久97牛牛 | 国产AV一区二区三区最新精品| 裸体美女洗澡啪啪裸J网站 | 日日噜噜夜夜狠狠久久丁香五月| 野花视频在线手机免费观看| 国产精品久久777777| 欧美成人精品三级网站| 亚洲国产精品无码久久久| 东北一家人1一6全文阅读小说| 猫咪WWW免费人成网站| 亚洲AV无码成人精品| 俄罗斯SEVERODVINSK| 免费人成在线观看网站品善网| 亚洲AV成人无码精品电影在线| 被窝影院午夜无码国产| 看黄A大片爽爽影院免费无码| 午夜男女爽爽影院免费视频下载| www.成人av| 麻花豆传媒剧国产入口| 亚洲AV无码国产精品夜色午夜| 丰满爆乳无码一区二区三区| 男人GAY自慰吞精网站| 亚洲精品国偷自产在线| 国产精产国品一二三产区区别 | 薄白丝小仙女自慰喷水| 麻花传媒剧国产MV高清播放| 亚洲AV中文无码乱人伦在线观看| 国产AV无码一区二区二三区J| 欧美老妇疯狂XXXXBBBB| 影帝隔着内裤滑进去了H| 激情男女高潮射精AV免费| 无码A级毛片免费视频内谢| 成人毛片100免费观看| 欧美肥胖老太大喷水| 一二三四在线视频社区3| 黑人巨大精品欧美一区二区| 无码人妻精品一区二区三区不卡| 潮喷大喷水系列无码| 欧美黑人又大又粗XXXXX| 再深点灬舒服灬太大了添A| 精品久久久久久久无码人妻热| 无码国内精品久久人妻| 高清毛茸茸的中国少妇| 日本熟妇人妻XXXXX视频| MM131巨爆乳美女少妇动态图| 免费 成 人 黄 色 网站69| 一本久久伊人热热精品中文| 精品国精品国产自在久国产不卡 | 玩弄中年熟妇正在播放| 大荫蒂又大又长又硬又紧又粗| 人妻熟女一区二区AⅤ波多野结衣| 18禁黄网站禁片免费观看国产| 久久亚洲AV成人无码| 亚洲图片小说激情综合| 精品熟女少妇AV免费久久| 亚洲高清毛片一区二区| 国色天香精品一卡2卡3卡 | 天天想你视频免费观看西瓜| 大陆国语对白国产AV片| 日本久久夜夜一本婷婷| 插我一区二区在线观看| 日本丰满人妻熟妇BBBBB| 扒开两腿中间缝流白浆在线看| 妺妺坐在我腿上勃起弄了视频| 中文字幕无码家庭乱欲| 免费人成激情视频在线观看冫| 中文无码制服丝袜人妻AV | 久久久久亚洲AV成人网| 一本大道色卡1卡2卡3乱码| 久久中文字幕无码专区| 在线精品一区二区三区| 免费A级毛片18禁| FREE紧VIDEOXX粗又长| 人妻丰满熟妇AⅤ无码区| 吃瓜网51CG7爆料| 婷婷久久综合九色综合97| 国产精品美女一区二区三区| 性色AV闺蜜一区二区三区| 交换朋友夫妻客厅互换4韩国 | 久久人人爽人人爽人人片Ⅴ| 尤物在线视频.YW163.成年| 蜜桃视频在线观看| JIZZJIZZJIZZ日本| 日日摸夜夜添夜夜添无| 国产激情无码一区二区| 亚洲AV无码国产精品色午夜字幕| 娇妻玩4P被3个男子伺候| 亚洲婷婷五月色香综合缴情| 久久亚洲精品无码GV| 99久无码中文字幕一本久道| 全免费A级毛片免费看无码| 丰满人妻被粗大爽ⅩXOO| 无码专区一ⅤA亚洲V专区在线| 韩国免费A级作爱片视频| 一本一道AⅤ无码中文字幕| 年轻老师的滋味3在观整有限中字| 爸的比老公大两倍儿媳妇怎么称呼| 少妇人妻AV无码专区| 国产性天天综合网| 一区二区清无吗视频| 欧洲PAYPAL网站WWW| 国产AV一区二区三区| 亚洲AV日韩精品久久久久| 久久久久久亚洲精品无码| CHINESE FREE 高清| 天堂8在线天堂资源在线| 激情内射人妻1区2区3区| 最新无码人妻在线不卡| 日韩久久一区二区三区蜜桃| 国产手机在线精品| 中国国产高清免费AV片| 日本做受高潮好舒服视频| 和人妻隔着帘子按摩中字 | 嫩草国产福利视频一区二区| 大象国精产品一品二品在线| 亚洲AⅤ无码乱码在线观看性色| 久久亚洲男人第一AV网站| 波多野结衣AV无码久久一区| 亚洲 春色 另类 小说| 麻豆XXXXXX在线观看| 东京热人妻无码人AV| 亚洲欧洲日产V一个人免费观看视频WWW高清 | 白又丰满大屁股BBBBB| 亚洲AV熟女高潮一区二区| 妺妺窝人体色7777777| 国产成人精品久久久久| 亚洲中字幕日产2021草莓 | 亚洲成人免费AV| 欧美极品少妇XXXX亚洲精品| 国产麻豆精品久久一二三| 中文无码日韩欧免费视频| 天天躁日日躁狠狠躁性色AVQ| 久久无码人妻丰满熟妇区毛片| 成人乱婬AV日日摸夜夜爽| 亚洲国产精品无码第一区二区三区| 欧美肥妇BWBWBWBXX| 国精产品 自偷自偷| PYTHON人马大战CSDN| 亚洲产在线精品亚洲第一站一| 秋霞无码AⅤ一区二区三区|