最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js實(shí)現(xiàn)分片上傳斷點(diǎn)續(xù)傳示例詳解

 更新時(shí)間:2022年07月29日 09:22:18   作者:來了老弟  
這篇文章主要為大家介紹了Node.js實(shí)現(xiàn)分片上傳斷點(diǎn)續(xù)傳示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

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

解決步驟:

  • 文件分片,減少每次請(qǐng)求消耗的時(shí)間,如果某次請(qǐng)求失敗可以單獨(dú)上傳,而不是從頭開始
  • 通知服務(wù)端合并文件分片
  • 控制并發(fā)的請(qǐng)求數(shù)量,避免瀏覽器內(nèi)存溢出
  • 當(dāng)因?yàn)榫W(wǎng)絡(luò)或者其他原因?qū)е履炒蔚恼?qǐng)求失敗,我們重新發(fā)送請(qǐng)求

文件的分片與合并

在JavaScript中,F(xiàn)Ile對(duì)象是' Blob '對(duì)象的子類,該對(duì)象包含一個(gè)重要的方法slice,通過該方法我們可以這樣分割二進(jìn)制文件:

<!DOCTYPE html>
<html lang="en">
<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);
            // 所有分片上傳完成,通知服務(wù)器合并分片
            await axios({
                method: "get",
                url: "/merge",
                params: {
                    filename: file.name,
                },
            });
            console.log("Upload to complete");
        }
    </script>
</body>
</html>

并發(fā)控制

如果文件很大,這樣切分的分片會(huì)很多,瀏覽器短時(shí)間內(nèi)就會(huì)發(fā)起大量的請(qǐng)求,可能會(huì)導(dǎo)致內(nèi)存耗盡,所以要進(jìn)行并發(fā)控制。

這里我們結(jié)合Promise.race()方法 控制并發(fā)請(qǐng)求的數(shù)量,避免瀏覽器內(nèi)存溢出。

// 加入并發(fā)控制
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(() => {
        // 從并發(fā)池中移除已經(jīng)完成的請(qǐng)求
        let index = pool.findIndex((t) => t === task);
            pool.splice(index);
        });
        // 把請(qǐng)求放入并發(fā)池中,如果已經(jīng)達(dá)到最大并發(fā)量
        pool.push(task);
        if (pool.length === max) {
            //All requests are requested complete
            await Promise.race(pool);
        }
    }
    // 所有分片上傳完成,通知服務(wù)器合并分片
    await axios({
        method: "get",
        url: "/merge",
        params: {
            filename: file.name,
        },
    });
    console.log("Upload to complete");
}

使代碼可復(fù)用

function SliceUpload() {
    const file = document.getElementById('fileInput').files[0]
    if (!file) return
    // 文件分片
    let size = 1024 * 50; // 分片大小設(shè)置
    let fileChunks = [];
    let index = 0;        // 分片序號(hào)
    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){
            // 所有分片上傳完成,通知如無(wú)
            await axios({
                method: 'get',
                url: '/merge',
                params: {
                    filename: file.name
                }
            });
            console.log('Upload to complete')
            return
        }
        let pool = []       // 并發(fā)池
        let max = 3         // 最大并發(fā)數(shù)
        let finish = 0      // 完成數(shù)量
        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)=>{
                // 從并發(fā)池中移除已經(jīng)完成的請(qǐng)求
                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)
}

服務(wù)端接口實(shí)現(xiàn)

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)

以上就是Node.js實(shí)現(xiàn)分片上傳示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Node.js分片上傳的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • node.js-v6新版安裝具體步驟(分享)

    node.js-v6新版安裝具體步驟(分享)

    下面小編就為大家?guī)硪黄猲ode.js-v6新版安裝具體步驟(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • 說說如何利用 Node.js 代理解決跨域問題

    說說如何利用 Node.js 代理解決跨域問題

    這篇文章主要介紹了Node.js代理解決跨域問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • nodejs如何將高版本降為低版本

    nodejs如何將高版本降為低版本

    在遇到項(xiàng)目依賴低版本Node.js時(shí),直接安裝低版本可能會(huì)遇到困難,本文提供了一種通過卸載當(dāng)前高版本Node.js并使用NVM(Node Version Manager)來管理和安裝低版本Node.js的方法,首先,需要卸載現(xiàn)有的Node.js環(huán)境并清理相關(guān)文件
    2024-10-10
  • NodeJs生成sitemap站點(diǎn)地圖的方法示例

    NodeJs生成sitemap站點(diǎn)地圖的方法示例

    這篇文章主要介紹了NodeJs生成sitemap站點(diǎn)地圖的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • 深入剖析Node.js cluster模塊

    深入剖析Node.js cluster模塊

    Node的單線程設(shè)計(jì)已經(jīng)沒法更充分的"壓榨"機(jī)器性能了,Node新增了一個(gè)內(nèi)置模塊cluster,它可以通過一個(gè)父進(jìn)程管理一坨子進(jìn)程的方式來實(shí)現(xiàn)集群的功能,這篇文章主要介紹了深入剖析Node.js cluster模塊,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Node.js中Sequelize?hook的使用方法小結(jié)

    Node.js中Sequelize?hook的使用方法小結(jié)

    Sequelize?提供了多個(gè)?hook,用于在執(zhí)行數(shù)據(jù)庫(kù)操作時(shí)執(zhí)行一些自定義邏輯,本文為大家整理了一些常用的?Sequelize?hook?列表及其作用,希望對(duì)大家有所幫助
    2024-02-02
  • Node 升級(jí)到最新穩(wěn)定版的方法分享

    Node 升級(jí)到最新穩(wěn)定版的方法分享

    今天小編就為大家分享一篇Node 升級(jí)到最新穩(wěn)定版的方法分享,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • Linux系統(tǒng)中利用node.js提取Word(doc/docx)及PDF文本的內(nèi)容

    Linux系統(tǒng)中利用node.js提取Word(doc/docx)及PDF文本的內(nèi)容

    這篇文章主要給大家介紹了關(guān)于Linux系統(tǒng)中利用node.js提取Word(doc/docx)及PDF文本的內(nèi)容,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面跟著小編來一起看看吧。
    2017-06-06
  • 深入理解NodeJS 多進(jìn)程和集群

    深入理解NodeJS 多進(jìn)程和集群

    這篇文章主要介紹了深入理解NodeJS 多進(jìn)程和集群,詳細(xì)的介紹了什么是進(jìn)程和進(jìn)程的實(shí)現(xiàn)等,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-10-10
  • 在Node.js中判定文件是否可執(zhí)行的方法詳解

    在Node.js中判定文件是否可執(zhí)行的方法詳解

    在進(jìn)行前端開發(fā)時(shí),經(jīng)常需要處理各種文件權(quán)限的問題,特別是在Node.js環(huán)境中,你可能想要判斷某個(gè)文件是否具有可執(zhí)行權(quán)限,本文將詳細(xì)介紹如何使用isexe模塊來進(jìn)行這一操作,需要的朋友可以參考下
    2024-05-05

最新評(píng)論

理塘县| 读书| 云南省| 阿拉善右旗| 大安市| 台湾省| 高清| 南郑县| 玉环县| 池州市| 西畴县| 广宗县| 奈曼旗| 浙江省| 武平县| 尉氏县| 汉寿县| 石渠县| 云阳县| 射洪县| 略阳县| 冕宁县| 沅江市| 尤溪县| 随州市| 蒙山县| 清苑县| 咸宁市| 崇文区| 凤山县| 阳泉市| 肥城市| 察雅县| 连云港市| 松潘县| 濉溪县| 鄂伦春自治旗| 安庆市| 临邑县| 武汉市| 阆中市|