前端大文件断点续传

断点续传在前端开发中通常用于处理大文件上传的情况,以减少网络波动对上传过程的影响,并提高用户体验。

步骤:

  1. 创建 Vue 项目: 使用 Vue CLI 创建一个新项目。
  2. 安装 Axios: 如果你选择使用 Axios 而不是原生的 fetch
  3. 编写组件: 创建一个包含文件输入框、上传按钮和进度条的 Vue 组件。
  4. 编写逻辑: 处理文件读取、分块、发送请求以及进度更新。

所需依赖:前提需搭建好vue项目

npm install --save axios

代码示例

<template>
  <div>
    <input type="file" @change="handleFileChange" ref="fileInput" />
    <button @click="startUpload">开始上传</button>
    <button @click="pauseUpload">暂停上传</button>
    <button @click="resumeUpload">继续上传</button>
    <progress :value="progress" max="100"></progress>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      file: null,
      fileReader: null,
      blobURL: '',
      xhr: null,
      progress: 0,
      chunkSize: 1 * 1024 * 1024, // 1MB
      currentChunk: 0,
      isPaused: false,
      lastUploadedByte: 0
    };
  },
  methods: {
    handleFileChange(event) {
      this.file = event.target.files[0];
      this.fileReader = new FileReader();
      this.blobURL = URL.createObjectURL(this.file);
      this.fileReader.onload = () => {
        this.lastUploadedByte = this.getLastUploadedByte(); // Load from storage
      };
      this.fileReader.readAsArrayBuffer(this.file);
    },
    startUpload() {
      if (!this.file) return;
      this.isPaused = false;
      this.uploadNextChunk();
    },
    pauseUpload() {
      if (this.xhr) {
        this.xhr.abort();
        this.isPaused = true;
      }
    },
    resumeUpload() {
      this.startUpload();
    },
    uploadNextChunk() {
      if (this.currentChunk * this.chunkSize > this.file.size) {
        console.log('Upload completed!');
        return;
      }

      const start = this.currentChunk * this.chunkSize;
      const end = Math.min(start + this.chunkSize, this.file.size);

      const blob = this.file.slice(start, end);
      const formData = new FormData();
      formData.append('file', blob, this.file.name);
      formData.append('start', start.toString());
      formData.append('end', end.toString());

      this.xhr = axios.post('/api/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
          'Last-Uploaded-Byte': this.lastUploadedByte.toString()
        },
        onUploadProgress: progressEvent => {
          this.progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
        }
      }).then(response => {
        this.currentChunk++;
        this.lastUploadedByte = end;
        this.storeLastUploadedByte(this.lastUploadedByte);
        if (!this.isPaused) {
          this.uploadNextChunk();
        }
      }).catch(error => {
        console.error('Error uploading:', error);
      });
    },
    getLastUploadedByte() {
      return parseInt(localStorage.getItem('lastUploadedByte')) || 0;
    },
    storeLastUploadedByte(byte) {
      localStorage.setItem('lastUploadedByte', byte);
    }
  }
};
</script>

后端接口:

你需要确保你的后端服务器支持断点续传。这通常涉及到检查请求头中的 Last-Uploaded-Byte 字段,并根据这个字段返回已上传的字节数。

以上代码展示了一个基本的 Vue.js 组件,它可以处理文件选择、文件分块并上传每个分块到服务器。此外,它还支持暂停和恢复上传操作,并记录已上传的字节数以便下次上传时可以从上次中断的地方继续。

详细解释:

Vue 组件结构:
  • HTML: 包含一个文件输入框、三个按钮和一个进度条。
  • Vue 数据模型: 定义了用于存储文件数据、上传状态等的变量。
  • 方法:
    • handleFileChange: 当用户选择文件时触发,读取文件内容,并加载上次上传的位置。
    • startUpload: 开始上传文件,从第一块开始。
    • pauseUpload: 暂停上传过程,取消当前的 XMLHttpRequest 请求。
    • resumeUpload: 重新开始上传过程。
    • uploadNextChunk: 上传文件的下一块,并递归调用自身直到完成所有块。
    • getLastUploadedByte: 从本地存储加载最后上传的字节数。
    • storeLastUploadedByte: 将最后上传的字节数保存到本地存储。
Vue 逻辑详解:
  1. 文件选择:

    • 当用户通过 <input type="file"> 选择文件后,handleFileChange 方法被触发。
    • 文件被读取到内存中,同时从本地存储中加载最后上传的字节数。
  2. 开始上传:

    • 用户点击“开始上传”按钮后,startUpload 方法被调用。
    • 方法首先检查是否有文件被选择,然后初始化上传过程,设置 isPaused 为 false 并调用 uploadNextChunk
  3. 暂停与继续:

    • “暂停上传”按钮调用 pauseUpload 方法,如果当前有上传请求进行,则取消该请求。
    • “继续上传”按钮调用 resumeUpload 方法,重新开始上传过程。
  4. 分块上传:

    • uploadNextChunk 方法负责将文件分割成块并上传每一块。
    • 它计算出当前块的起始位置和结束位置,并创建一个 blob 对象来代表这一块。
    • 使用 FormData 将 blob 和元数据(起始位置和结束位置)添加到请求中。
    • 发送请求给服务器,并监听上传进度。
  5. 进度条更新:

    • 在每次上传请求中,都监听 onUploadProgress 事件,根据已上传的数据量更新进度条的值。
  6. 断点续传:

    • 每次成功上传一个块后,都会更新 currentChunk 和 lastUploadedByte
    • 通过 storeLastUploadedByte 方法将 lastUploadedByte 存储到浏览器的 localStorage 中,以便在页面刷新或关闭后仍能恢复上传。
    • 通过 getLastUploadedByte 方法从 localStorage 中加载 lastUploadedByte

后端接口:

你需要确保你的后端服务器支持断点续传。这通常涉及到检查请求头中的 Last-Uploaded-Byte 字段,并根据这个字段返回已上传的字节数。

注意事项:

  • 错误处理: 以上示例代码中没有包括详细的错误处理逻辑。在实际应用中,你可能需要增加更多的错误捕获和重试机制。
  • 性能优化: 对于非常大的文件,可能还需要考虑其他优化策略,比如并发上传多个块等。
  • 安全性: 在真实的生产环境中,还需要考虑文件的验证、权限控制等问题。

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值