摘要:大文件上傳的實現準備階段大文件上傳的過程中需要用到發布訂閱模式監聽上傳的進度發布訂閱模式的實現事件棧獲取事件對應棧的索引事件類型對應棧的索引不存在為已有事件類型處理棧監聽事件自定義事件類型事件處理函數已存在事件類型處理直接把相應的處理函
大文件上傳的實現
準備階段:
大文件上傳的過程中需要用到發布訂閱模式監聽上傳的進度
發布訂閱模式的實現
export default class { // 事件棧 eventStacks = [{ eventType: "", handlers: [] }]; /** * 獲取事件對應棧的索引 * * @param {string} eventType 事件類型 * @return {number} stackIndex 對應棧的索引 不存在為-1 */ indexOf(eventType) { const eventStacks = this.eventStacks; // 已有事件類型處理棧 let stackIndex = -1; for (let i = 0; i < eventStacks.length; i++) { const eventStack = eventStacks[i]; if (eventStack.eventType === eventType) { stackIndex = i; break; } } return stackIndex; }; /** * 監聽事件 * * @param {string} eventType 自定義事件類型 * @param {Function} handler 事件處理函數 */ on(eventType, handler) { const index = this.indexOf(eventType); if (index >= 0) { // 已存在事件類型處理 直接把相應的處理函數入棧 this.eventStacks[index].handlers.push(handler); } else { // 不存在事件,把對應的事件處理入棧 const newEventStack = { eventType, handlers: [handler] }; this.eventStacks.push(newEventStack); } }; /** * 觸發對應的事件 * * @param {string} eventType 自定義事件類型 * @param {Object} params 參數對象 */ emit(eventType, params = {}) { this.execEvent(eventType, params); }; /** * 執行對應的事件 * * @param {string} eventType 自定義事件類型 * @param {Object} params 參數對象 */ execEvent(eventType, params = {}) { const index = this.indexOf(eventType); if (index < 0) { return; } const handlers = this.eventStacks[index].handlers; for (let i = 0; i < handlers.length; i++) { const currentHandler = handlers[i]; if (currentHandler && typeof currentHandler === "function") { currentHandler(params); } } }; /** * 解除對應的事件 * * @param {string} eventType 事件類型 * @param {Function} handler 事件處理器 必須是引用傳進來 使用對象引用相等判斷 */ offHandler(eventType, handler) { const index = this.indexOf(eventType); if (index >= 0 && this.eventStacks[index].handlers.length) { // 存在,并且已經入棧 const handlers = this.eventStacks[index].handlers; this.eventStacks[index].handlers = handlers.filter(currentHandler => { return currentHandler !== handler }); } } }
文件是基于Blob BlobMDN文檔
Blob 類型可以使用slice截取一段 基于這點 我們就可以吧大文件拆分成很多小的文件塊上傳 前端實現如下:
import superagent from "superagent"; import eventEmitter from "../util/eventEmitter"; // 上傳單個文件 export const uploadFile = (file, url) => { const formData = new FormData(); formData.set("image", file); console.log(file.size); return superagent.post(url) .send(formData); }; // 獲取文件分塊之后的數量 const getFragmentNum = (file, fragmentSize) => { // fragmentSize 拆分文件的大小 return Math.ceil(file.size / fragmentSize); }; // 獲取文件碎片 const getFileFragment = (file, start, end, fragmentSize) => { return file.slice(start * fragmentSize, end * fragmentSize); }; const getSlicedFiles = (file, fragmentSize) => { const slicedFiles = []; // 獲取文件分塊的數量 const fragmentNum = getFragmentNum(file, fragmentSize); // 獲取所有的分塊文件 for (let i = 0; i < fragmentNum; i++) { const currentFileFragment = getFileFragment(file, i, i + 1, fragmentSize); slicedFiles.push(currentFileFragment); } return slicedFiles; }; // 多文件上傳 export class uploadBigFile extends eventEmitter { constructor(file, url, fragmentSize) { super(); // 拆分的文件數組 const slicedFiles = getSlicedFiles(file, fragmentSize); // 正在上傳的模塊 this.currentIndex = 0; this.uploadSlicedFiles(slicedFiles, url); }; /** * 上傳拆分后的文件 * * @param {Array} files 文件數組 * @param {string} url 上傳的地址 */ uploadSlicedFiles(files, url) { uploadFile(files[this.currentIndex], url) .then(({body}) => { this.emit("process", { currentIndex: this.currentIndex, res: body, progress: (this.currentIndex + 1) / files.length }); this.currentIndex++; if (this.currentIndex < files.length) { this.uploadSlicedFiles(files, url); } }) .catch(err => { console.log(err); }); }; }
后端實現如下:
const express = require("express"); const router = express.Router(); const multer = require("multer"); const upload = multer(); // multer用于接受formdata router.post("/upload", upload.single("image"), (req, res) => { res.send({ code: 0, file: req.file.size }); }); module.exports = router;
效果如圖 :
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105510.html
摘要:話前上傳大文件上傳的教程網上很多但是大部分沒給出一個比較完整的出來這個博客給出的是前后端一套完整的解決方案其中前端沒有使用第三方上傳庫希望能幫到有同樣需求的朋友們大文件分片上傳的好處在這里就不用多說了之前不管是上傳單文件還是分片文件上傳都是 話前 上傳大文件上傳的教程網上很多, 但是大部分沒給出一個比較完整的出來, 這個博客給出的是前后端一套完整的解決方案, 其中前端沒有使用第三方上傳...
摘要:大文件上傳主要分為三部分,預上傳,分塊上傳,合并上傳??梢詳U展此對象來控制上傳頭部。是完成最終的大文件合并上傳。修改可以控制發送哪些攜帶數據。 由于業務需要,需要上傳大文件,已有的版本無法處理IE版本,經過調研,百度的 webuploader 支持 IE 瀏覽器,而且支持計算MD5值,進而可以實現秒傳的功能。 大文件上傳主要分為三部分,預上傳,分塊上傳,合并上傳。 預上傳:計算MD5值...
摘要:分片上傳主要是前端將一個較大的文件分成等分的幾片,標識當前分片是第幾片和總共幾片,待所有的分片均上傳成功的時候,在后臺進行合成文件即可。 一、前言 在網站開發中,經常會有上傳文件的需求,有的文件size太大直接上傳,經常會導致上傳過程中耗時太久,大量占用帶寬資源,因此有了分片上傳。 分片上傳主要是前端將一個較大的文件分成等分的幾片,標識當前分片是第幾片和總共幾片,待所有的分片均上傳成...
閱讀 1096·2021-11-24 10:24
閱讀 2584·2021-11-22 13:54
閱讀 992·2021-09-24 09:55
閱讀 3592·2019-08-30 15:54
閱讀 1311·2019-08-30 15:44
閱讀 1089·2019-08-30 14:23
閱讀 3195·2019-08-29 13:45
閱讀 1267·2019-08-29 11:19