当前位置:首页 > VUE

vue实现大文件下载

2026-02-21 08:30:16VUE

使用分片下载实现大文件下载

在Vue中实现大文件下载,可以采用分片下载的方式,避免内存溢出和网络中断问题。以下是具体实现方法:

安装axios库:

vue实现大文件下载

npm install axios

创建下载工具函数:

import axios from 'axios';

export function downloadLargeFile(url, fileName, chunkSize = 1024 * 1024) {
  const controller = new AbortController();

  axios({
    url,
    method: 'HEAD',
    signal: controller.signal
  }).then(response => {
    const totalSize = response.headers['content-length'];
    const totalChunks = Math.ceil(totalSize / chunkSize);

    const promises = [];
    for (let i = 0; i < totalChunks; i++) {
      const start = i * chunkSize;
      const end = Math.min(start + chunkSize - 1, totalSize - 1);

      promises.push(
        axios.get(url, {
          headers: { Range: `bytes=${start}-${end}` },
          responseType: 'blob'
        })
      );
    }

    return Promise.all(promises);
  }).then(chunks => {
    const blob = new Blob(chunks.map(chunk => chunk.data));
    const downloadUrl = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = downloadUrl;
    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    window.URL.revokeObjectURL(downloadUrl);
    document.body.removeChild(link);
  }).catch(error => {
    if (error.name !== 'AbortError') {
      console.error('下载失败:', error);
    }
  });

  return controller;
}

显示下载进度

添加进度显示功能可以提升用户体验:

vue实现大文件下载

export function downloadWithProgress(url, fileName, onProgress) {
  return new Promise((resolve, reject) => {
    axios({
      url,
      method: 'GET',
      responseType: 'blob',
      onDownloadProgress: progressEvent => {
        if (onProgress) {
          const percent = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          onProgress(percent);
        }
      }
    }).then(response => {
      const blob = new Blob([response.data]);
      const downloadUrl = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = downloadUrl;
      link.download = fileName;
      document.body.appendChild(link);
      link.click();
      window.URL.revokeObjectURL(downloadUrl);
      document.body.removeChild(link);
      resolve();
    }).catch(reject);
  });
}

断点续传实现

对于超大文件,实现断点续传功能:

export function resumeDownload(url, fileName, savedChunks = []) {
  const controller = new AbortController();

  axios({
    url,
    method: 'HEAD',
    signal: controller.signal
  }).then(response => {
    const totalSize = response.headers['content-length'];
    const downloadedSize = savedChunks.reduce((sum, chunk) => sum + chunk.size, 0);

    if (downloadedSize >= totalSize) {
      const blob = new Blob(savedChunks);
      // 触发下载
      return;
    }

    const remainingSize = totalSize - downloadedSize;
    const chunkSize = 1024 * 1024; // 1MB
    const totalChunks = Math.ceil(remainingSize / chunkSize);

    const promises = [];
    for (let i = 0; i < totalChunks; i++) {
      const start = downloadedSize + i * chunkSize;
      const end = Math.min(start + chunkSize - 1, totalSize - 1);

      promises.push(
        axios.get(url, {
          headers: { Range: `bytes=${start}-${end}` },
          responseType: 'blob'
        }).then(res => {
          savedChunks.push(res.data);
          return res.data.size;
        })
      );
    }

    return Promise.all(promises);
  }).then(() => {
    const blob = new Blob(savedChunks);
    // 触发下载
  }).catch(error => {
    console.error('下载失败:', error);
  });

  return controller;
}

在Vue组件中使用

在Vue组件中调用下载功能:

<template>
  <div>
    <button @click="startDownload">下载大文件</button>
    <div v-if="progress > 0">
      下载进度: {{progress}}%
    </div>
  </div>
</template>

<script>
import { downloadWithProgress } from './downloadUtils';

export default {
  data() {
    return {
      progress: 0
    };
  },
  methods: {
    startDownload() {
      const url = 'https://example.com/large-file.zip';
      const fileName = 'large-file.zip';

      downloadWithProgress(url, fileName, (percent) => {
        this.progress = percent;
      }).then(() => {
        this.$message.success('下载完成');
      }).catch(() => {
        this.$message.error('下载失败');
      });
    }
  }
};
</script>

注意事项

  1. 服务器必须支持Range请求头才能实现分片下载
  2. 大文件下载会占用较多内存,建议分片大小根据实际情况调整
  3. 断点续传需要本地存储已下载的分片数据
  4. 考虑添加下载取消功能,避免资源浪费

这些方法可以根据实际需求组合使用,实现稳定可靠的大文件下载功能。

标签: 大文件vue
分享给朋友:

相关文章

vue实现收起展开面板

vue实现收起展开面板

实现收起展开面板的方法 在Vue中实现收起展开面板功能可以通过多种方式完成,以下是几种常见的实现方法: 使用v-show或v-if控制显示隐藏 利用Vue的指令可以轻松实现面板的展开和收起:…

vue公共列表的实现

vue公共列表的实现

实现 Vue 公共列表组件 公共列表组件通常用于展示重复结构的数据,例如商品列表、用户列表等。以下是一个典型的实现方式: 基础实现 创建可复用的列表组件 List.vue: <templ…

vue实现语音

vue实现语音

Vue 实现语音功能的方法 使用 Web Speech API Vue 可以结合 Web Speech API 实现语音识别和合成功能。Web Speech API 包含 SpeechRecognit…

vue 实现blog

vue 实现blog

Vue 实现博客的基本步骤 使用 Vue 实现博客可以分为前端和后端两部分,前端使用 Vue.js 框架,后端可以选择 Node.js、Python 或其他服务端语言。以下是一个基于 Vue 的博客实…

vue实现高亮

vue实现高亮

Vue 实现文本高亮的方法 在 Vue 中实现文本高亮可以通过多种方式完成,以下是几种常见的方法: 方法一:使用 v-html 指令 通过 v-html 指令可以动态插入 HTML 内容,将需…

vue 实现挂载

vue 实现挂载

Vue 实现挂载的基本方法 在 Vue 中,挂载是将 Vue 实例与 DOM 元素关联的过程。通过挂载,Vue 可以管理 DOM 并实现数据绑定和响应式更新。 创建 Vue 实例并挂载 const…