vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue iview分片上传

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

作者:小茗同学阿

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

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

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

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

前提条件

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分片上传内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文