基于Vue 和 iView分片上传功能实现(上传组件)

 更新时间:2025年01月08日 09:48:00   作者:小茗同学阿  
本文介绍了基于Vue和iView的文件分片上传技术,通过将文件拆分成多个小块并逐块上传,解决了大文件上传时的诸多问题,如上传速度慢、超时和网络中断等,它还展示了如何实现分片上传的进度显示、错误处理和断点续传等功能,感兴趣的朋友跟随小编一起看看吧

在实际开发中,上传大文件往往会面临一些问题,如上传速度慢、超时、网络中断等。为了更好地解决这些问题,我们可以使用分片上传技术。分片上传就是将文件拆分成多个小块进行上传,每个小块称为“分片”,上传成功后,服务器会将这些分片重新合并成完整的文件。

本文将通过一个基于 Vue 和 iView 的分片上传示例,详细介绍如何实现文件分片上传,并且为每个上传的分片提供上传进度显示和错误处理。

使用分片上传技术的优势:

  • 提高上传成功率:即使某个分片上传失败,只需要重新上传该分片,其他分片不受影响。
  • 支持断点续传:分片上传可以帮助我们实现断点续传功能。
  • 支持上传大文件:通过将大文件切分成小的分片,避免一次性上传造成的超时问题。

前提条件

  • Vue.js:用于构建用户界面。
  • iView:一款基于 Vue 的 UI 组件库,其中包括用于文件上传的 Upload 组件。
  • Axios:用于发起 HTTP 请求,进行文件上传。
  • 后端 API:需要提供分片上传和文件合并接口。

1. 组件结构

首先,使用 iView 提供的 Upload 组件来构建文件上传界面,界面中包含一个选择文件按钮和一个上传进度条。在 Vue 的 data 中定义上传所需的一些变量,例如文件分片大小、上传进度、分片的集合等。

<template>
  <div>
    <!-- iView的Upload组件 -->
    <Upload
      :action="uploadAction"
      :before-upload="beforeUpload"
      :on-progress="handleProgress"
      :on-success="handleSuccess"
      :on-error="handleError"
      :show-file-list="false"
      :headers="uploadHeader"
    >
      <Button>选择文件</Button>
    </Upload>
    <div v-if="uploading">
      <Progress :percent="uploadProgress"></Progress>
    </div>
  </div>
</template>

在上面的代码中,使用了 iView 的 Upload 组件来处理文件选择,Progress 组件用来展示文件上传的进度。before-upload 用于文件上传前的预处理,on-progress 用来更新进度条,on-successon-error 用来处理上传成功或失败的回调。

2. 数据结构

data() {
  return {
    uploadHeader: { 
      Authorization: localStorage.token,  // 上传请求的授权头
      Accept: '*/*'  // 允许所有类型的响应
    },
    fileName: '', // 存储文件名
    fileSize: 0,  // 存储文件大小
    chunkSize: 5 * 1024 * 1024,  // 每个分片的大小,这里设置为5MB
    fileChunks: [],  // 存储文件的所有分片
    uploading: false,  // 是否正在上传
    uploadProgress: 0,  // 上传进度
    currentChunkIndex: 0,  // 当前上传的分片索引
    uploadAction: `${this.baseURL}/xxxx`,  // 上传分片的API
    uploadActionMerge: `${this.baseURL}/xxx`,  // 合并分片的API
  };
}

data 中,定义了上传的必要参数,包括文件名、文件大小、分片大小、上传进度等。uploadActionuploadActionMerge 分别表示上传分片和合并文件的 API 地址。

3. 处理文件上传前的操作

当文件被选中后,触发 before-upload 回调函数,在该函数中我们进行文件的验证和分片处理。

// 上传前的验证和分片操作
beforeUpload (file) {
  // 如果需要做格式验证,大小检查等,可以在这里添加验证逻辑
  this.fileName = file.name;  // 记录文件名称
  this.fileSize = file.size;  // 记录文件大小
  // 调用分片处理方法
  this.chunkFile(file);
  return false;  // 返回false表示不直接上传,手动上传
},

4. 分片处理

chunkFile(file) {
  const totalChunks = Math.ceil(file.size / this.chunkSize);  // 计算分片数量
  this.fileChunks = [];  // 清空分片数组
  // 循环切割文件为多个分片
  for (let i = 0; i < totalChunks; i++) {
    const start = i * this.chunkSize;
    const end = Math.min(start + this.chunkSize, file.size);
    const chunk = file.slice(start, end);
    this.fileChunks.push(chunk);  // 将当前分片添加到分片数组
  }
  this.uploading = true;  // 设置上传状态为进行中
  this.uploadNextChunk();  // 上传第一个分片
}

chunkFile 方法中,我们通过计算文件的总大小和每个分片的大小来确定分片数量,并将文件切割成多个分片。然后,我们将每个分片存储在 fileChunks 数组中,并开始上传第一个分片。

5. 上传分片

上传每个分片时,我们使用 FormData 来构造上传的表单数据,并使用 axios 发送 HTTP 请求。

uploadChunk(chunk) {
  const clientId = this.generateClientId();  // 生成唯一的客户端ID
  const formData = new FormData();
  formData.append('file', chunk);  // 添加分片
  formData.append('clientId', clientId);  // 客户端ID
  formData.append('chunkId', this.currentChunkIndex);  // 当前分片索引
  this.axios.post(this.uploadAction, formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
    onUploadProgress: (event) => {
      const hasUploadTotal = this.currentChunkIndex * this.chunkSize;
      const percent = Math.round((hasUploadTotal + event.loaded) * 100 / this.fileSize); // 计算上传进度
      this.uploadProgress = percent;  // 更新进度
    },
  }).then(res => {
    if (res.data.code === 1) {
      this.currentChunkIndex++;  // 上传成功,增加分片索引
      this.uploadNextChunk(clientId);  // 上传下一个分片
    } else {
      this.$message.error('上传失败');
      this.uploading = false;
    }
  }).catch(error => {
    this.$message.error('上传失败');
    this.uploading = false;
  });
}

6. 合并文件

当所有分片上传完成后,我们需要调用后端接口来合并这些分片,最终生成完整的文件。

mergeFile(clientId, fileName) {
  const url = `${this.uploadActionMerge}&clientId=${clientId}&sourceName=${fileName}`;
  this.axios.post(url).then(({ data }) => {
    if (data.code === 1) {
      this.$message.success('上传成功');
    } else {
      this.$message.warning(data.message);
    }
  }).catch((err) => {
    this.$message.error('合并文件出错');
  }).finally(() => {
    // 重置状态
    this.resetUploadState();
  });
}

7. 生成客户端ID

为了确保每次上传都能被唯一标识,我们使用当前时间戳和随机数生成一个客户端ID。

generateClientId() {
  const timestamp = (+new Date()).toString(32);  // 时间戳转为32进制
  let randomStr = '';
  // 随机生成字符
  for (let i = 0; i < 5; i++) {
    randomStr += Math.floor(Math.random() * 65535).toString(32);
  }
  return timestamp + randomStr;  // 返回客户端ID
}

8. 上传进度

通过 onUploadProgress 回调函数,我们可以在文件上传过程中动态地更新进度条,实时展示上传进度。

handleProgress(event) {
  const hasUploadTotal = this.currentChunkIndex * this.chunkSize;
  const percent = Math.round((hasUploadTotal + event.loaded) * 100 / this.fileSize);  // 计算总上传进度
  this.uploadProgress = percent;  // 更新进度条
}

9. 上传成功和失败处理

最后,我们还可以在上传成功或失败时,进行相应的处理。

handleSuccess(response) {
  this.$message.success('上传成功');
  this.uploading = false;
}
handleError(error) {
  this.$message.error('上传失败');
  this.uploading = false;
}

总结

通过以上步骤,成功实现了基于 Vue 和 iView 组件的分片上传功能。主要流程包括:文件选择、文件分片、逐个分片上传、上传进度显示以及文件合并等。该方案对于大文件上传具有较好的稳定性和效率,尤其适用于大文件的分片上传场景。

到此这篇关于基于Vue 和 iView分片上传功能实现(上传组件)的文章就介绍到这了,更多相关vue iview分片上传内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • VUE中computed 、created 、mounted的先后顺序说明

    VUE中computed 、created 、mounted的先后顺序说明

    这篇文章主要介绍了VUE中computed 、created 、mounted的先后顺序说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 浅谈Vue 数据响应式原理

    浅谈Vue 数据响应式原理

    这篇文章主要介绍了浅谈Vue 数据响应式原理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • Vue3应对后端接口返回十万条数据的解决方案

    Vue3应对后端接口返回十万条数据的解决方案

    在前端开发中,我们有时会遇到后端接口直接返回 十万条数据 的情况,很多初学者会直接把数据全部 v-for 渲染到页面上,结果浏览器瞬间卡死甚至崩溃,本文将从问题原因出发,逐步给出几种常见解决方案,需要的朋友可以参考下
    2025-09-09
  • vue3+elementui-plus实现一个接口上传多个文件功能

    vue3+elementui-plus实现一个接口上传多个文件功能

    这篇文章主要介绍了vue3+elementui-plus实现一个接口上传多个文件,先使用element-plus写好上传组件,然后假设有个提交按钮,点击上传文件请求接口,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-07-07
  • Vue设置长时间未操作登录自动到期返回登录页

    Vue设置长时间未操作登录自动到期返回登录页

    这篇文章主要介绍了Vue设置长时间未操作登录以后自动到期返回登录页,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2020-01-01
  • vue 解决数组赋值无法渲染在页面的问题

    vue 解决数组赋值无法渲染在页面的问题

    今天小编就为大家分享一篇vue 解决数组赋值无法渲染在页面的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • ElementUI的this.$notify.close()调用不起作用的解决

    ElementUI的this.$notify.close()调用不起作用的解决

    本文主要介绍了ElementUI的this.$notify.close()调用不起作用的解决,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Vue项目生产环境性能优化的实战技巧

    Vue项目生产环境性能优化的实战技巧

    本文总结了Vue项目生产环境性能优化的实战技巧,这些优化能显著提升Vue应用的速度、稳定性和资源效率,文章通过代码示例介绍的非常详细,需要的朋友可以参考下
    2025-08-08
  • 关于Vue3中的响应式原理

    关于Vue3中的响应式原理

    这篇文章主要介绍了关于Vue3中的响应式原理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Vue中transition单个节点过渡与transition-group列表过渡全过程

    Vue中transition单个节点过渡与transition-group列表过渡全过程

    这篇文章主要介绍了Vue中transition单个节点过渡与transition-group列表过渡全过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04

最新评论