久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合

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

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號
久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合
国产探花一区| 国产suv精品一区| 日韩视频一区| 亚洲激情另类| 免费日韩av片| 日韩激情综合| 久久精品国产成人一区二区三区| 久久一区国产| 色在线中文字幕| 久久国产亚洲| 日韩中文字幕1| 伊人久久大香伊蕉在人线观看热v| 日本不卡视频一二三区| 麻豆久久久久久| 福利一区二区免费视频| 欧美日韩国产亚洲一区| 午夜精品影视国产一区在线麻豆| 国产精品日本一区二区不卡视频| 人人草在线视频| 亚洲综合三区| 精品久久免费| 国产手机视频一区二区| 国产精品分类| 日韩视频一区| 精品女同一区二区三区在线观看| 日韩在线看片| 欧美日韩精品一区二区三区视频 | 国产精品一级在线观看| 手机在线电影一区| 日韩在线播放一区二区| 麻豆国产精品| 激情综合在线| 日韩88av| 日韩高清在线不卡| 九色porny丨国产首页在线| 亚洲久久在线| 日本а中文在线天堂| 99成人超碰| 日本三级亚洲精品| 色婷婷色综合| 日韩av不卡一区二区| 欧美日中文字幕| 国产高清亚洲| 日韩有码av| 黄色av一区| zzzwww在线看片免费| 中文字幕乱码亚洲无线精品一区| 久久精品五月| 亚洲精品激情| 99视频精品全国免费| 国产精品18| 亚洲欧洲日韩| se01亚洲视频 | 亚洲精品视频一二三区| 国产v综合v| 免费在线成人| 日韩精品一区二区三区中文在线 | 精品1区2区3区4区| 美女国产一区二区三区| 亚洲免费网址| 激情综合自拍| 伊人网在线播放| 国产伦精品一区二区三区视频| 99视频一区| 亚洲天堂资源| 久久99久久久精品欧美| 一区二区国产精品| 欧美aa国产视频| 国产一区国产二区国产三区| 日本va欧美va瓶| 男人天堂欧美日韩| 精品一区欧美| 日韩精品影视| 免费看一区二区三区| 日韩一二三区在线观看| 久久不射网站| 99re国产精品| 好看的av在线不卡观看| 亚洲天堂黄色| 99久久久久国产精品| 电影天堂国产精品| 色一区二区三区四区| 卡一卡二国产精品| 国产精品极品国产中出| 久久国产婷婷国产香蕉| 综合欧美亚洲| 亚洲精品系列| 人人爱人人干婷婷丁香亚洲| 亚洲欧美日韩国产综合精品二区 | 国产精品一区二区免费福利视频| 综合激情一区| 蜜桃视频免费观看一区| 免费在线观看视频一区| 在线精品视频一区| 日本成人中文字幕| 日韩av午夜在线观看| 日本不卡视频一二三区| 奇米狠狠一区二区三区| 国产精品一线| 国产精品一区高清| 久热精品在线| 成人日韩在线观看| 国产精品对白| 久久gogo国模啪啪裸体| 国产精品一区二区三区美女| 国产精品v日韩精品v欧美精品网站 | 亚洲三级欧美| 欧美日韩在线二区| 国产一在线精品一区在线观看| 99视频精品视频高清免费| 欧美成人a交片免费看| 亲子伦视频一区二区三区| 国产麻豆久久| 黄色成人91| 亚洲+小说+欧美+激情+另类| 日韩在线网址| 精品99在线| 免费观看不卡av| 日韩专区欧美专区| 欧美aa在线视频| 久久三级福利| 婷婷亚洲成人| 精品亚洲自拍| 亚洲一级特黄| 日韩欧美三区| 欧美精品不卡| 欧美精品资源| 亚洲精品国产精品粉嫩| 精品三级在线| 午夜精品免费| 国产精品一区二区av日韩在线| 亚洲精品永久免费视频| 视频一区视频二区中文| 久久不见久久见国语| 999精品色在线播放| 日韩在线麻豆| 成人日韩在线| 日韩精品电影一区亚洲| 国产资源在线观看入口av| 久热精品在线| 精品视频在线观看网站| 国产中文一区| 天堂va欧美ⅴa亚洲va一国产| 精品久久久中文字幕| 欧美日韩免费观看一区=区三区| 日本va欧美va欧美va精品| 色婷婷久久久| 欧美日韩在线精品一区二区三区激情综合| 国产一区二区三区天码| 美女被久久久| 色偷偷色偷偷色偷偷在线视频| 亚洲精品黄色| 国产综合亚洲精品一区二| 麻豆91小视频| 美女精品在线| 国产不卡av一区二区| 丝袜诱惑制服诱惑色一区在线观看| 国产欧美一区二区三区米奇 | 欧美日韩视频免费观看| 日本视频一区二区| 五月婷婷亚洲| 麻豆视频观看网址久久| 综合激情一区| 精品一区三区| 日韩久久视频| 国产乱人伦丫前精品视频| 一区在线免费观看| 在线中文字幕播放| 国产精品草草| 亚洲精品日本| 黄色亚洲大片免费在线观看| 精品72久久久久中文字幕| 日韩在线观看一区二区三区| 99久久精品国产亚洲精品| 国产精品流白浆在线观看| 丝袜亚洲精品中文字幕一区| 久久精品av| 在线亚洲人成| 另类欧美日韩国产在线| 久久国产日韩欧美精品| 视频一区二区不卡| 在线精品小视频| 免费看av不卡| 久久精品国产99国产| 91成人福利| 一二三区精品| 99视频在线精品国自产拍免费观看| 成人免费网站www网站高清| 成人日韩av| 久久精品国产99国产| 欧美激情日韩| 国产精品久久亚洲不卡| 国产亚洲一卡2卡3卡4卡新区| 亚洲免费福利一区| 亚洲bt欧美bt精品777| 日本在线成人| 欧美日韩网址| 国产精品亚洲综合久久| 国产免费av国片精品草莓男男| 亚洲精品一二三**|