Vue 大文件上传和断点续传的实现

2023-12-19

实现 Vue 大文件上传和断点续传需要掌握以下几个步骤:

分片:将大文件分割成若干个小块,便于上传。一般采用 Blob 对象或 ArrayBuffer 来实现。
上传:将分片文件上传到服务器。可以使用 XMLHttpRequest、Fetch 等工具进行上传。
断点续传:如果上传失败或上传过程中断开连接,需要记录已上传的分片,下次上传时跳过已上传的分片。
合并:上传完成后,将所有分片文件合并成一个完整的文件。
以下是一个例子,展示如何使用 Vue.js 实现大文件上传和断点续传:

安装依赖
首先需要安装一些依赖,包括 axios、js-sha256 等,可以使用 npm 或 yarn 进行安装:

npm install axios js-sha256

分片和上传
在前端实现分片和上传时需要考虑以下几个问题:

如何分片:可以根据文件大小或自定义的分片大小进行分割,一般使用 Blob 对象或 ArrayBuffer 储存。
如何上传:可以使用 XMLHttpRequest、Fetch 等工具进行上传,需要在请求头中添加一些信息,如文件名、片数、当前片数、是否续传等。
以下是一个使用 axios 进行上传的示例代码:

const uploadFile = (file) => {
  const chunkSize = 4 * 1024 * 1024; // 4MB
  const fileSize = file.size;
  const chunks = Math.ceil(fileSize / chunkSize);
  const sha256Promise = sha256(file);

  const config = {
    headers: {
      'Content-Type': file.type,
      'X-File-Name': encodeURIComponent(file.name),
      'X-File-Size': fileSize,
      'X-File-Chunks': Math.ceil(fileSize / chunkSize),
      'X-File-Hash': '',
    },
  };

  return sha256Promise.then(hash => {
    config.headers['X-File-Hash'] = hash;

    let promises = [];
    for (let i = 0; i < chunks; i++) {
      const start = i * chunkSize;
      const chunk = file.slice(start, start + chunkSize);

      const formData = new FormData();
      formData.append('chunk', chunk);
      formData.append('chunkNumber', i + 1);
      formData.append('chunksTotal', chunks);

      promises.push(
        axios.post('/api/upload', formData, config)
      );
    }

    return axios.all(promises);
  });
};

断点续传
在上传过程中发生中断或失败时,需要从中断点处继续上传。为实现断点续传,需要在服务器端记录已上传的分片,前端发送请求时携带这些信息,服务器判断后返回还需要上传哪些分片。如果没有中断,需要检查文件是否已完整上传。

以下是一个使用 axios 进行断点续传的示例代码:

const uploadFile = (file) => {
  const chunkSize = 4 * 1024 * 1024; // 4MB
  const fileSize = file.size;
  const chunks = Math.ceil(fileSize / chunkSize);
  const sha256Promise = sha256(file);

  let config = {
    headers: {
      'Content-Type': file.type,
      'X-File-Name': encodeURIComponent(file.name),
      'X-File-Size': fileSize,
      'X-File-Chunks': Math.ceil(fileSize / chunkSize),
      'X-File-Hash': '',
    },
  };

  const checkUploadedChunks = () => {
    return axios.post('/api/check', {
      filename: encodeURIComponent(file.name),
      filesize: fileSize,
      filechunks: Math.ceil(fileSize / chunkSize),
    }).then(response => {
      return response.data;
    });
  };

  return sha256Promise.then(hash => {
    config.headers['X-File-Hash'] = hash;
    return checkUploadedChunks();
  }).then(uploadedChunks => {
    if (uploadedChunks.length === chunks) {
      return Promise.resolve();
    }

    const formData = new FormData();
    for (let i = 0; i < chunks; i++) {
      if (uploadedChunks.includes(i + 1)) {
        continue;
      }

      const start = i * chunkSize;
      const chunk = file.slice(start, start + chunkSize);

      formData.append('chunk', chunk);
      formData.append('chunkNumber', i + 1);
      formData.append('chunksTotal', chunks);
    }

    return axios.post('/api/upload', formData, config);
  });
};

合并
当所有分片都上传完成之后,需要在服务器端对这些分片进行合并,生成完整的文件。如果中间有分片上传失败或中断,需要在下次上传时跳过这些分片。

以下是一个使用 Node.js 进行合并的示例代码:

const fs = require('fs');
const path = require('path');

const mergeChunks = (form) => {
  const filename = decodeURIComponent(form.get('filename'));
  const fileSize = form.get('filesize');
  const chunksTotal = form.get('filechunks');
  const tempDir = path.join('temp', filename);

  const chunks = Array.from(form.entries())
    .filter(([key, value]) => key.startsWith('chunk-'))
    .map(([key, value]) => {
      const number = parseInt(key.slice(6), 10);
      const chunkFilePath = path.join(tempDir, `${filename}.${number}`);
      return {
        number,
        filename: chunkFilePath,
        size: value.length,
      };
    })
    .sort((a, b) => a.number - b.number);

  if (chunks.length !== chunksTotal) {
    console.log(`文件[${filename}]分片数量[${chunks.length}]不符要求[${chunksTotal}]`);
    return Promise.reject();
  }

  const writeStream = fs.createWriteStream(path.join('uploads', filename));

  return new Promise((resolve, reject) => {
    let offset = 0;
    const doWrite = () => {
      const chunk = chunks.shift();
      if (!chunk) {
        writeStream.end();
        console.log(`文件[${filename}]已写入`);
        resolve();
        return;
      }

      const readStream = fs.createReadStream(chunk.filename, { highWaterMark: chunk.size });
      readStream.pipe(writeStream, { end: false });
      readStream.on('error', reject);
      readStream.on('end', () => {
        console.log(`分片[${chunk.number}]已写入`);
        offset += chunk.size;
        doWrite();
      });
    };

    doWrite();
  });
};

参考文章:http://blog.ncmem.com/wordpress/2023/12/19/vue-%e5%a4%a7%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%92%8c%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0%e7%9a%84%e5%ae%9e%e7%8e%b0/
欢迎入群一起讨论

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue 大文件上传和断点续传的实现 的相关文章

  • 主干视图 DOM 元素已删除

    我一直在阅读有关 Backbone js 僵尸 或内存泄漏 问题的信息 基本上 当您不再需要该元素时 您必须从 DOM 中解除绑定并删除该元素 以确保所有事件也被删除 现在 我有一个包含几个容器的单页应用程序 div div div div
  • Android 设备上的 PhoneGap 蓝牙插件

    我一直在尝试让 PhoneGap 工作的蓝牙插件 但我似乎不知道哪里出了问题 首先 我的测试设备是 Galaxy S3 GT 19305T 应用程序是使用PhoneGap CLI http docs phonegap com en 3 0
  • 每 3 秒重复一次动画

    我正在使用 WOW js 和 animate css 现在我正在将 CSS 运行到 Infinite 我想知道如何让我的课程运行 3 秒停止并再次开始到无限 My html img src images fork png class for
  • 不和谐机器人 |不和谐.js |类型错误:无法读取未定义的属性“长度”

    我正在制作一个 Discord 机器人 并且正在使用 CodeLyon 的视频作为参考 该错误位于我的 message js 文件中 该文件包含以下内容 require dotenv config create cooldowns map
  • 使用 Angular 下载具有动态 src 的脚本

    Angular 提供了通过动态名称动态加载模板的方法ng include 该部分中的内联 JS 和 CSS 可以正常加载 但没有一个好的方法来下载带有动态 url 的脚本 我们需要下载脚本 相对于调用它们的 html 部分的路径 即我们有一
  • 如何监听 jQuery AJAX 请求?

    以下两种实现 ajaxRequest 1 2 的方法应该是等效的 话说回来 为什么验证回调已执行的单元测试 3 在 1 中成功而在 2 中失败 我应该如何重写测试 3 来监视 2 中的成功回调 如果我尝试stub jQuery ajax使用
  • 从未用 @flow 标记的导入文件中获取类型定义

    TL DR我怎么告诉flow从未声明的导入模块导入类型定义 flow 加长版 流接缝能够从不使用流语法的文件中派生类型 请参阅示例 示例文件 flow js if Math random lt 0 5 var y hello else va
  • 在requestAnimationFrame中使用clearRect不显示动画

    我正在尝试在 HTML5 画布上做一个简单的 javascript 动画 现在我的画布是分层的 这样当我收到鼠标事件时 背景层不会改变 但带有头像的顶层会移动 如果我使用 requestAnimationFrame 并且不清除屏幕 我会看到
  • 跟踪用户何时点击浏览器上的后退按钮

    是否可以检测用户何时单击浏览器的后退按钮 我有一个 Ajax 应用程序 如果我可以检测到用户何时单击后退按钮 我可以显示适当的数据 任何使用 PHP JavaScript 的解决方案都是优选的 任何语言的解决方案都可以 只需要我可以翻译成
  • 在javascript中解析json - 长数字被四舍五入

    我需要解析一个包含长数字的 json 在 java servlet 中生成 问题是长数字被四舍五入 当执行这段代码时 var s x 6855337641038665531 var obj JSON parse s alert obj x
  • 如何获取 vuejs 组件单元测试中定义的“this”变量

    我正在尝试在 npm 脚本中使用 mocha webpack 来测试 vuejs 组件 我在测试中像这样嘲笑 vuex 商店 const vm new Vue template div div
  • 提交表单并重定向页面

    我在 SO 上看到了很多与此相关的其他问题 但没有一个对我有用 我正在尝试提交POST表单 然后将用户重定向到另一个页面 但我无法同时实现这两种情况 我可以获取重定向或帖子 但不能同时获取两者 这是我现在所拥有的
  • 为 illustrator 导出脚本以保存为 web jpg

    任何人都可以帮我为 illustrator CC2017 编写一个脚本 将文件以 JPG 格式导出到网络 旧版 然后保存文件并关闭 我有 700 个文件 每个文件有 2 个画板 单击 文件 gt 导出 gt 另存为 Web 旧版 然后右键文
  • 为什么在 Internet Explorer 中访问 localStorage 对象会引发错误?

    我正在解决一个客户端问题 Modernizr 意外地没有检测到对localStorageInternet Explorer 9 中的对象 我的页面正确使用 HTML 5 文档类型 并且开发人员工具报告该页面具有 IE9 的浏览器模式和 IE
  • HTML 离线应用程序缓存,列出下载的文件

    作为我正在构建的离线 Web 应用程序的加载屏幕的一部分 使用缓存清单 http developer apple com library safari documentation iPhone Conceptual SafariJSData
  • 模块构建失败(来自 ./node_modules/babel-loader/lib/index.js)Vue Js

    我从 GitHub 下载了一个我和我的朋友正在开发的项目 但是当我尝试运行时 npm run serve 我收到这个错误 src main js 中的错误 Module build failed from node modules babe
  • 在 vue.js 中访问数组对象属性

    给定以下数组vue js packageMaps Object packageMap 0 Object Id 16 PackageType flag list ProductCode F BannerBase packageMap 1 Ob
  • 为什么 jquery 没有检测到单选按钮未被选中的情况? [复制]

    这个问题在这里已经有答案了 可能的重复 JQuery radioButton change 在取消选择期间不会触发 https stackoverflow com questions 5176803 jquery radiobutton c
  • 导致回发到与弹出窗口不同的页面

    我有一个主页和一个详细信息页面 详细信息页面是从主页调用的 JavaScript 弹出窗口 当单击详细信息页面上的 保存 按钮时 我希望主页 刷新 是否有一种方法可以调用主页的回发 同时还可以从详细信息页面维护保存回发 Edit 使用win
  • fullCalendar 未显示正确的结束日期

    我正在看调试页面 http jsbin com wukofacaxu edit js outputFullCalendar 官方网站的 我想安排一个活动时间为 22 09 2015 至 30 09 2015 dd mm yyyy 但它只显示

随机推荐

  • AntDB-T提升查询性能的关键之查询优化解析

    查询优化器 是提升查询效率非常重要的手段 本文将主要介绍 AntDB T数据库查询优化 的相关设计 AntDB T数据库是一款企业级通用分布式关系型数据库 而查询是AntDB T数据库管理系统中最关键 最吸引人的功能之一 每个生产数据库系统
  • FAM amine, 6-isomer,1313393-44-0,含有纯6-异构体的荧光团,6-FAM NH2

    产品名称 FAM amine 6 isomer 6 FAM NH2 中文名称 6 羧基荧光素 氨基 CAS 1313393 44 0 分子式 C27H26N2O6 分子量 474 51 纯度 95 结构式 产品描述 荧光素衍生物具有胺基 含
  • 自定义WheelView

    项目中用到一个比较觉得不错的控件 WheelView 即上下滚动View 它是继承ScrollView实现 在Android各版本上的效果都是如下 也许在git上有许多这样功能的控件 但个人认为这个控件实现的方式简单 比较让人容易理解 对自
  • Zookeeper 和 Dubbo 的关系?

    Zookeeper的作用 zookeeper用来注册服务和进行负载均衡 哪一个服务由哪一个机器来提供必需让调用者知道 简单来说就是ip地址和服务名称的对应关系 当然也可以通过硬编码的方式把这种对应关系在调用方业务代码中实现 但是如果提供服务
  • java 员工绩效管理系统Myeclipse开发mysql数据库MVC结构serlvet编程计算机网页项目

    一 源码特点 java 员工绩效管理系统是一套完善的java web信息管理系统 对理解JSP java编程开发语言有帮助 系统采用serlvet dao bean 系统具有完整的源代码和数据库 系统主要采用B S模式开发 开发工具myec
  • 64.Oracle19cPDB的创建和删除

    1 创建PDB CREATE PLUGGABLE DATABASE DB CROSS ADMIN USER pdbadmin IDENTIFIED BY enmo 2023 ROLES dba DEFAULT TABLESPACE CROS
  • Linux中seLinux是什么?关闭会造成哪些影响?

    seLinux是一种安全增强型的Linux操作系统 其主要作用是强化系统的安全性和保护系统资源免受未经授权的访问和攻击 其提供了三种工作模式 分别是Disabled工作模式 Permissive工作模式和Enforcing工作模式 那么Li
  • CNN和TCN的区别和联系

    CNN 卷积神经网络 和TCN 时间卷积网络 都是神经网络的变体 用于处理不同类型的数据 以下是它们的主要区别和联系 区别 应用领域 CNN 主要用于处理图像数据 具有在空间维度上捕捉局部特征的能力 常用于计算机视觉任务 TCN 主要用于处
  • Python中的定时器用法:Timer定时器和schedule库

    目录 一 引言 二 Timer定时器 1 Timer定时器的原理 2 Timer定时器的使用方法 3 Timer定时器的实际应用案例 三 schedule库 1 schedule库的原理 2 schedule库的使用方法 3 schedul
  • 62.$ORACLE_HOME/.patch_storage是否可以删除

    1 此目录为是Oracle打补丁时被替换的文件的备份 是的 即使成功安装了补丁程序 也必须保留 ORACLE HOME patch storage目录 1 将临时补丁应用到Oracle主目录时 OPatch将补丁信息存储在 ORACLE H
  • Linux-----13、用户、组

    用户 组 一 用户管理 用户概念及作用 了解 用户 指的是Linux操作系统中用于管理系统或者服务的人 一问 管理系统到底在 管理什么 答 Linux下一切皆 文件 所以用户管理的是相应的文件 二问 如何管理 文件呢 答 文件基本管理 比如
  • 宿主机和容器

    宿主机 Host 和容器 Container 是 Docker 中的两个重要概念 描述了 Docker 环境中的两个主要部分 宿主机 Host 宿主机是指安装了 Docker 引擎 Docker Engine 的物理计算机或虚拟机 它是 D
  • 从 MySQL 到 DolphinDB,Debezium + Kafka 数据同步实战

    Debezium 是一个开源的分布式平台 用于实时捕获和发布数据库更改事件 它可以将关系型数据库 如 MySQL PostgreSQL Oracle 等 的变更事件转化为可观察的流数据 以供其他应用程序实时消费和处理 本文中我们将采用 De
  • VSCode 代码高亮 变量类型、函数名、类名没有颜色 - 设置主题即可

    https zhuanlan zhihu com p 630401039 之前应该设置主题了 但不知道为啥C 里面只有 int 有高亮 其他像 cv Mat 函数名 类名都没有颜色 解决方案是重新设置一下主题 File preference
  • 使用SQL和Python处理Excel文件数据

    目录 一 引言 二 使用SQL查询Excel文件数据 1 导入必要的库 2 创建数据库连接 3 读取Excel文件数据 4 将数据写入数据库 5 使用SQL查询数据 三 使用Python读取和处理Excel文件数据 1 导入必要的库 2 读
  • ES elasticsearch-analysis-dynamic-synonym连接数据库动态更新synonym近义词

    ES elasticsearch analysis dynamic synonym连接数据库动态更新synonym近义词 修改源码实现连接数据库获取近义词汇 下载elasticsearch analysis dynamic synonym打
  • 移动端界面布局适配方案

    自适应和响应式 1 自适应 根据不同的设备大小来自动调整尺寸 大小 2 响应式 会随着屏幕的实时变动而自动调整 是一种自适应 移动端视口 能看到的区域就是视口 viewport fixed就是相对于视口来进行定位的 在PC端视口就只有一个
  • 基于SpringBoot+Vue的智慧校园之家长子系统设计实现(源码+lw+部署文档+讲解等)

    文章目录 前言 详细视频演示 具体实现截图 技术栈 后端框架SpringBoot 前端框架Vue 持久层框架MyBaitsPlus 系统测试 系统测试目的
  • MSDN:Mutually Semantic Distillation Network for Zero-Shot Learning 中文版 待更新

    摘要 零样本学习 ZSL 的关键挑战是如何将潜在的语义知识融合在可见类的视觉特征和抽象特征之间 从而实现向不可见类的横向知识转移 之前的工作要么只是将图像的全局特征与其相关的类语义向量对齐 要么利用单向注意力来学习有限的潜在语义表示 这无法
  • Vue 大文件上传和断点续传的实现

    实现 Vue 大文件上传和断点续传需要掌握以下几个步骤 分片 将大文件分割成若干个小块 便于上传 一般采用 Blob 对象或 ArrayBuffer 来实现 上传 将分片文件上传到服务器 可以使用 XMLHttpRequest Fetch