A detailed implementation tutorial for uploading large file slices in Vue projects to realize second transmission and breakpoint resume transmission

1. Inspection points

In the Vue project, uploading large files such as large pictures and multi-data Excel is a very common requirement. However, due to the large file size, the upload speed is very slow, and problems such as transmission interruption are inevitable. Therefore, in order to improve the efficiency and success rate of uploading, we need to use slice uploading to implement functions such as file transfer in seconds, resuming transfer from breakpoints, error retry, concurrency control, etc., and draw a progress bar.

In this article, we examine this technique from three perspectives:

Technical solution: How to implement functions such as slice upload, file transfer in seconds, breakpoint resume, error retry, and concurrency control;
code example: based on the Vue framework, how to use the axios library and element-ui component library to realize the above functions;
summary: the advantages and limitations of this technology, recommended application scenarios and future development directions.

2. Technical solution

1. Implement slice upload

Slice upload refers to dividing a large file into several small pieces for uploading, which not only reduces the pressure on the server, but also improves upload efficiency. We use the File API for file slicing, which splits the file into fixed size chunks (eg each chunk is 1MB in size) and uploads each chunk to the server via FormData.

2. File transfer in seconds

File transfer in seconds means that when the same file is uploaded, if the file already exists on the server, there is no need to upload it again, but the address of the file that already exists in the server is returned directly. The realization of file transfer in seconds can be judged by calculating the MD5 check value of the file.

3. Resume upload

Breakpoint resume upload means that when the file upload is interrupted, the upload can continue from the previous breakpoint when uploading again without re-uploading the entire file. To achieve resuming uploads, you can record the upload progress and the upload status of each block (uploaded, not uploaded, upload failed), and judge the blocks that need to be uploaded based on these information when uploading.

4. Error retry

Upload may fail due to network etc. In order to avoid upload failures, we need error handling and retries for the upload process. We can set a maximum number of retries, and retry after the upload fails until the maximum number of retries is reached.

5. Control concurrency

Since uploading requires bandwidth and server resources, uploading multiple files or multiple chunks at the same time may cause bandwidth and server resource constraints. Therefore, we need to limit the number of files and blocks uploaded at the same time to prevent excessive use of bandwidth and server resources.

3. Code example

The following is a sample code based on the Vue framework, using the axios library and the element-ui component library to implement slice uploading:

<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>

The above code implements a simple slice upload function, including file transfer in seconds, resuming upload from breakpoints, error retry, concurrency control and other functions, and draws a progress bar.

Four. Summary

Slice upload technology is a very practical technology, especially suitable for uploading large files. It can not only improve the upload efficiency and success rate, but also reduce the pressure on the server. However, the slice uploading technology also has its limitations, for example, the file needs to be preprocessed before uploading, and the server needs to support this technology. Therefore, when using slice upload technology, you need to weigh the pros and cons and choose a solution that suits you.

In the future, with the continuous development of hardware and network technology, slice upload technology will be more widely used, and there will be more optimizations and improvements to make it more efficient, stable and easy to use.

Guess you like

Origin blog.csdn.net/weixin_63929524/article/details/130463327