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

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

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

正文

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

解決步驟:

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

文件的分片與合并

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

<!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ā)控制

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

這里我們結(jié)合Promise.race()方法 控制并發(fā)請求的數(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)完成的請求
        let index = pool.findIndex((t) => t === task);
            pool.splice(index);
        });
        // 把請求放入并發(fā)池中,如果已經(jīng)達到最大并發(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;        // 分片序號
    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 = []       // 并發(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)完成的請求
                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ù)端接口實現(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實現(xiàn)分片上傳示例詳解的詳細內(nèi)容,更多關(guān)于Node.js分片上傳的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

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

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

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

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

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

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

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

    NodeJs生成sitemap站點地圖的方法示例

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

    深入剖析Node.js cluster模塊

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

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

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

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

    今天小編就為大家分享一篇Node 升級到最新穩(wěn)定版的方法分享,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    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)容,文中給出了詳細的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面跟著小編來一起看看吧。
    2017-06-06
  • 深入理解NodeJS 多進程和集群

    深入理解NodeJS 多進程和集群

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

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

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

最新評論

柳州市| 东源县| 息烽县| 资中县| 漯河市| 泰来县| 建湖县| 乐清市| 大连市| 车致| 元江| 漯河市| 福海县| 神农架林区| 和顺县| 漯河市| 柯坪县| 滨州市| 左权县| 武平县| 岑溪市| 渭源县| 长丰县| 郑州市| 民县| 尉犁县| 临潭县| 寿阳县| 鸡泽县| 万全县| 泊头市| 吴桥县| 富平县| 化隆| 崇信县| 赤壁市| 岱山县| 吐鲁番市| 会宁县| 合川市| 手游|