首页 > 其他分享 >Vue项目中大文件切片上传实现秒传、断点续传的详细实现教程

Vue项目中大文件切片上传实现秒传、断点续传的详细实现教程

时间:2023-10-27 13:35:32浏览次数:39  
标签:断点续传 教程 Vue const 文件 切片 file 上传

一、考察点
在Vue项目中,大图片和多数据Excel等大文件的上传是一个非常常见的需求。然而,由于文件大小较大,上传速度很慢,传输中断等问题也难以避免。因此,为了提高上传效率和成功率,我们需要使用切片上传的方式,实现文件秒传、断点续传、错误重试、控制并发等功能,并绘制进度条。

在本文中,我们将从以下三个角度考察这个技术:

技术方案:如何实现切片上传、文件秒传、断点续传、错误重试、控制并发等功能;
代码示例:基于Vue框架,如何使用axios库和element-ui组件库实现以上功能;
总结:该技术的优点和局限性,推荐应用场景和未来发展方向。

二、技术方案
1. 实现切片上传
切片上传是指将大文件分成若干小块进行上传,这样不仅减轻了服务器的压力,还可以提高上传效率。我们使用File API进行文件切割,将文件分割成固定大小的块(例如每个块的大小为1MB),并通过FormData将每个块上传到服务器。

2. 文件秒传
文件秒传是指当上传同一个文件时,如果该文件已经存在于服务器上,就不需要再次上传,而是直接返回服务器中已有该文件的地址。实现文件秒传可以通过计算文件的MD5校验值进行判断。

3. 断点续传
断点续传是指当文件上传中断时,再次上传时可以从上一次断点处继续上传,而不需要重新上传整个文件。实现断点续传可以记录上传进度,以及每个块上传的状态(已上传、未上传、上传失败),并在上传时根据这些信息判断需要上传的块。

4. 错误重试
由于网络等原因,上传可能会失败。为了避免上传失败,我们需要对上传过程进行错误处理和重试。我们可以设置一个最大重试次数,在上传失败后进行重试,直到达到最大重试次数为止。

5. 控制并发
由于上传需要占用带宽和服务器资源,同时上传多个文件或多个块可能会引起带宽和服务器资源紧张。因此,我们需要限制同时上传的文件数和块数,防止过度占用带宽和服务器资源。

三、代码示例
以下是一个基于Vue框架,使用axios库和element-ui组件库实现切片上传的示例代码:

<template>
  <div>
    <!--上传组件-->
    <el-upload
      class="upload-demo"
      :action="uploadUrl"  // 上传地址
      :auto-upload="false"  // 禁用自动上传
      :on-change="handleChange"  // 文件选择时触发
      :before-upload="handleBeforeUpload"  // 文件上传前触发
      :on-progress="handleProgress"  // 上传进度变化时触发
    >
      <el-button slot="trigger">选取文件</el-button>  // 选择文件按钮
      <!--上传文件按钮-->
      <el-button style="margin-left: 10px" type="primary" :loading="uploading" :disabled="files.length === 0" @click="handleUpload">
        上传文件
      </el-button>
      <div class="clearfix"></div>
      <el-progress :percentage="percent"></el-progress>  // 上传进度条
    </el-upload>
  </div>
</template><script>
import axios from 'axios';
import { ElMessage } from 'element-ui';  // 引入Element UI库中的消息提示组件export default {
  data() {
    return {
      files: [],  // 选中的文件列表
      uploading: false,  // 是否正在上传
      percent: 0,  // 上传进度
      uploadUrl: 'https://your.upload.url'  // 上传地址
    };
  },
  methods: {
    // 切片上传
    async upload(file) {
      const chunkSize = 1024 * 1024; // 每个块的大小为 1MB
      const fileSize = file.size;  // 文件大小
      const chunks = Math.ceil(fileSize / chunkSize);  // 总块数
      const tasks = [];  // 上传任务数组
      let uploaded = 0;  // 已上传块数      // 文件切割
      for (let i = 0; i < chunks; i++) {
        const start = i * chunkSize;
        const end = Math.min(start + chunkSize, fileSize);        tasks.push(
          new Promise((resolve, reject) => {
            const formData = new FormData();
            formData.append('chunk_index', i);  // 块编号
            formData.append('chunk_count', chunks);  // 总块数
            formData.append('file_id', file.id);  // 文件ID
            formData.append('chunk_data', file.slice(start, end));  // 块数据            axios
              .post(this.uploadUrl, formData)  // 上传块数据
              .then(res => {
                uploaded++;
                this.percent = Math.floor((uploaded / chunks) * 100);
                resolve();
              })
              .catch(err => {
                reject(err);
              });
          })
        );
      }      // 待所有块上传完成后,发送合并请求
      await Promise.all(tasks);
      const res = await axios.post(this.uploadUrl, { file_id: file.id, chunks });      // 上传成功,返回文件URL
      if (res.status === 200) {
        return `${this.uploadUrl}/${file.id}`;
      } else {
        throw new Error(res.data.message);
      }
    },
    handleChange(files) {
      this.files = files;
    },
    async handleUpload() {
      try {
        this.uploading = true;
        for (let i = 0; i < this.files.length; i++) {
          const file = this.files[i];
          const url = await this.upload(file);
          // 文件上传成功,将url展示给用户 
          ElMessage.success(`文件${file.name}上传成功!URL:${url}`);
        }
      } catch (err) {
        ElMessage.error(`文件上传失败!${err.message}`);
      } finally {
        this.uploading = false;
      }
    },
    handleBeforeUpload() {
      // TODO: 检查文件大小、类型等
    },
    handleProgress(event, file) {
      // 显示上传进度
      this.percent = Math.floor((event.loaded / event.total) * 100);
    }
  }
};
</script>

以上代码实现了一个简单的切片上传功能,包括文件秒传、断点续传、错误重试、控制并发等功能,并绘制进度条。

四、总结
切片上传技术是一种非常实用的技术,特别适用于大文件上传。它不仅可以提高上传效率和成功率,还可以减轻服务器的压力。但是,切片上传技术也有其局限性,例如上传前需要对文件进行预处理,同时服务器需要支持该技术。因此,在使用切片上传技术时需要权衡利弊,选择适合自己的方案。

未来,随着硬件和网络技术的不断发展,切片上传技术将会得到更广泛的应用,并且会有更多的优化和改进,使其更加高效、稳定和易用。

参考文章:http://blog.ncmem.com/wordpress/2023/09/22/vue项目中大文件切片上传实现秒传、断点续传的详/


 

标签:断点续传,教程,Vue,const,文件,切片,file,上传
From: https://blog.51cto.com/u_14023400/8053021

相关文章

  • 如何实现大文件上传:秒传、断点续传、分片上传
    前言文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好的办法,毕竟很少有人会忍受,当文件上传到一半中断后,继续上传却只能重头开始上传,这种让人不爽的体验。那有没有比较好的......
  • 无涯教程-Clojure - cons函数
    返回一个新序列,其中"x"是第一个元素,而"seq"是其余元素。cons-语法以下是语法。(consxseq)参数   - "x"是需要添加到序列中的元素。"seq"是元素的顺序列表。返回值 - 具有附加元素的新序列。cons-示例以下是Clojure中con的示例。(nsclojure.examp......
  • 无涯教程-Clojure - ns-name函数
    返回特定名称空间的名称。ns-name-语法以下是语法。(ns-namenamespace-name)参数   - "namespace-name"是需要找到的名称空间。返回值 - 名称空间的实际名称。ns-name-示例(nsclojure.examples.example(:require[clojure.set:asset])(:gen-c......
  • CentOS7系统放行TCP/UDP端口教程
    在使用CentOS7操作系统时,您需要放行某些端口,以便应用程序能够正常运行。下面是如何放行TCP/UDP端口的步骤。步骤1:SSH连接服务器使用SSH方式连接服务器,如果您不知道如何SSH连接服务器,可以查看该教程:SSH远程连接Linux服务器教程步骤2:确定要放行的端口在放行端口之前,您需要确定要......
  • php结合webuploader断点续传的实现
    最近公司项目需要用到断点续传,所以记录一下其中的坑使用到的主要技术webuploaderthinkphp5断点续传的思路:客户端:   1.获取文件md5(MD5是文件唯一标识,用来判断是否存在此文件,并且用作分片的文件夹名)   2.将文件分片   3.验证分片是否上传过,上传过直接跳......
  • Android入门教程 | RecyclerView使用入门
    想必大家对列表的表现形式已经不再陌生。手机上有联系人列表,文件列表,短信列表等等。本文讲述的是在Android开发中用RecyclerView来实现列表效果。使用步骤引入RecyclerView在app的build.gradle文件中添加引用。我们使用的是androidx包。gradle:dependencies{//........
  • 每日一练:无感刷新页面(附可运行的前后端源码,前端vue,后端node)
    1、前言想象下,你正常在网页上浏览页面。突然弹出一个窗口,告诉你登录失效,跳回了登录页面,让你重新登录。你是不是很恼火。这时候无感刷新的作用就体现出来了。2、方案2.1redis设置过期时间在最新的技术当中,token一般都是在Redis服务器存着,设置过期时间。只要在有效时间内,重新发出请......
  • vue 中的provide和inject用法。
     provide和inject可以用作vue组件的通讯-父子/跨级provide选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的property。inject选项应该是:一个字符串数组,或一个对象,对象的key是本地的绑定名,value是:在可用的注入内容中搜索用的key(字符串或Symbol......
  • makedown教程
    标题我展示的是一级标题我展示的是二级标题一级标题二级标题三级标题四级标题五级标题六级标题段落这是段落直接在末尾加上两个空格这是段落使用空格来换行直接换行效果字体斜体文字斜体文本粗体文本粗体文本粗斜体文本粗斜体文本分隔符删除线RUNOOB.......
  • VIte+Vue3 打包在本地 双击 index.html 打开项目
    npmi@vitejs/plugin-legacynpmi@babel/preset-envnpmiterserimportlegacyfrom'@vitejs/plugin-legacy';exportdefaultdefineConfig({base:"./",plugins:[vue(),legacy({targets:["defaults","not......