当前位置:首页 > VUE

vue大文件下载实现

2026-02-21 20:41:57VUE

Vue 大文件下载实现方案

前端分片下载

使用 axiosfetch 结合 Blob 对象实现分片下载,避免内存溢出。通过设置 Range 请求头控制下载范围。

async function downloadLargeFile(url, fileName) {
  const chunkSize = 1024 * 1024 * 5; // 5MB分片
  let startByte = 0;
  let endByte = chunkSize;
  const fileSize = await getFileSize(url); // 先获取文件总大小

  while (startByte < fileSize) {
    const response = await fetch(url, {
      headers: { 'Range': `bytes=${startByte}-${endByte}` }
    });
    const blob = await response.blob();
    saveChunk(blob, fileName, startByte === 0);
    startByte = endByte + 1;
    endByte = Math.min(startByte + chunkSize - 1, fileSize - 1);
  }
}

function saveChunk(blob, fileName, isFirstChunk) {
  const link = document.createElement('a');
  link.href = URL.createObjectURL(blob);
  link.download = fileName;
  link.style.display = 'none';
  document.body.appendChild(link);
  link.click();
  setTimeout(() => {
    URL.revokeObjectURL(link.href);
    document.body.removeChild(link);
  }, 100);
}

服务端配合

服务端需支持 Range 请求,返回 206 Partial Content 状态码。Node.js 示例:

app.get('/download', (req, res) => {
  const range = req.headers.range;
  const filePath = 'large-file.zip';
  const fileSize = fs.statSync(filePath).size;

  if (range) {
    const [start, end] = range.replace(/bytes=/, '').split('-');
    const chunkStart = parseInt(start, 10);
    const chunkEnd = end ? parseInt(end, 10) : fileSize - 1;

    res.writeHead(206, {
      'Content-Range': `bytes ${chunkStart}-${chunkEnd}/${fileSize}`,
      'Accept-Ranges': 'bytes',
      'Content-Length': chunkEnd - chunkStart + 1,
      'Content-Type': 'application/octet-stream'
    });

    fs.createReadStream(filePath, { start: chunkStart, end: chunkEnd })
      .pipe(res);
  } else {
    res.writeHead(200, {
      'Content-Length': fileSize,
      'Content-Type': 'application/octet-stream'
    });
    fs.createReadStream(filePath).pipe(res);
  }
});

进度显示优化

通过监听 onprogress 事件显示下载进度:

axios.get(url, {
  responseType: 'blob',
  onDownloadProgress: progressEvent => {
    const percent = Math.round(
      (progressEvent.loaded * 100) / progressEvent.total
    );
    console.log(`下载进度: ${percent}%`);
  }
}).then(response => {
  const url = window.URL.createObjectURL(new Blob([response.data]));
  const link = document.createElement('a');
  link.href = url;
  link.setAttribute('download', 'filename.ext');
  document.body.appendChild(link);
  link.click();
});

断点续传实现

利用 localStorage 存储已下载的字节位置:

let downloadedBytes = localStorage.getItem(fileName) || 0;

function resumeDownload(url, fileName) {
  const chunkSize = 1024 * 1024 * 5;
  let startByte = parseInt(downloadedBytes);
  let endByte = startByte + chunkSize - 1;

  fetch(url, {
    headers: { 'Range': `bytes=${startByte}-${endByte}` }
  }).then(response => {
    // ...处理分片
    localStorage.setItem(fileName, endByte + 1);
  });
}

Web Worker 处理

将耗时的下载逻辑放入 Web Worker 避免阻塞 UI:

vue大文件下载实现

// worker.js
self.onmessage = function(e) {
  const { url, fileName } = e.data;
  downloadLargeFile(url, fileName).then(() => {
    self.postMessage('done');
  });
};

// Vue组件中
const worker = new Worker('worker.js');
worker.postMessage({ url, fileName });
worker.onmessage = (e) => {
  if (e.data === 'done') console.log('下载完成');
};

注意事项

  • 浏览器对 Blob 对象有内存限制,分片大小需根据实际情况调整
  • 下载完成后及时调用 URL.revokeObjectURL() 释放内存
  • 服务端必须正确实现 Range 请求处理
  • 跨域请求需配置 CORS 和 Access-Control-Expose-Headers

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

相关文章

vue交互实现

vue交互实现

Vue 交互实现方法 Vue.js 提供了多种方式实现用户交互,包括事件处理、表单绑定、动态渲染等。以下是常见的交互实现方法: 事件处理 通过 v-on 或 @ 指令绑定事件,触发方法或直接执行表达…

vue 实现级联

vue 实现级联

Vue 实现级联选择器 级联选择器(Cascader)常用于省市区选择、分类选择等场景。Vue 中可以通过 Element UI、Ant Design Vue 等 UI 库实现,也可以手动封装。 使…

vue实现定位

vue实现定位

Vue 中实现定位的方法 在 Vue 中实现定位可以通过以下几种方式: 使用 CSS 定位 通过 CSS 的 position 属性实现定位,Vue 中可以直接在组件的 <style>…

vue搜索实现

vue搜索实现

Vue 搜索功能实现方法 基于计算属性的搜索 在 Vue 中可以通过计算属性实现简单的搜索功能。这种方式适合小型数据集,利用 JavaScript 的 filter 方法进行筛选。 data() {…

vue实现api

vue实现api

Vue 实现 API 调用 在 Vue 中调用 API 通常涉及使用 axios 或 fetch 发送 HTTP 请求,并结合 Vue 的响应式特性管理数据。以下是常见的实现方式: 安装 axios…

vue实现ftp

vue实现ftp

Vue 中实现 FTP 功能 Vue 本身是一个前端框架,无法直接操作 FTP 协议(FTP 通常需要后端支持)。以下是两种常见实现方式: 前端与后端配合实现 FTP 前端通过 API 与后端通信,…