当前位置:首页 > 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 示例:

vue大文件下载实现

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 事件显示下载进度:

vue大文件下载实现

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:

// 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中实现多级组件通常涉及父子组件嵌套,通过props向下传递数据,通过$emit向上传递事件。多级组件的核心是递归或动态组件渲染。 <!-- 父组件 Parent…

vue实现盖章

vue实现盖章

Vue 实现盖章功能 在Vue中实现盖章功能通常涉及前端UI交互,通过Canvas或SVG绘制印章,并允许用户拖拽或点击放置印章。以下是具体实现方法: 使用Canvas绘制印章 通过HTML5的Ca…

vue能实现

vue能实现

Vue.js 是一个流行的前端框架,能够实现多种功能。以下是 Vue 能够实现的主要功能和特性: 响应式数据绑定 Vue 的核心特性之一是响应式数据绑定。通过数据驱动视图,当数据发生变化时,视图会自…

vue实现频道

vue实现频道

Vue实现频道功能的方法 使用Vue Router动态路由 通过Vue Router的动态路由功能可以轻松实现频道切换。在路由配置中定义动态参数,组件内通过this.$route.params获取当前…

vue 实现全屏

vue 实现全屏

Vue 实现全屏功能 在 Vue 中实现全屏功能可以通过浏览器提供的 Fullscreen API 完成。以下是一个完整的实现方案: 安装依赖(可选) 如果需要跨浏览器兼容性更好,可以安装…

vue实现链接

vue实现链接

Vue 实现链接的方法 在 Vue 中实现链接可以通过多种方式,包括使用 <router-link>、<a> 标签或编程式导航。以下是几种常见的方法: 使用 <rout…