当前位置:首页 > 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 中实现复选框可以通过 v-model 指令绑定数据,同时结合 input 元素的 type="checkbox" 属性来实现。以下是几种常见的实现方式: 单个复选框…

vue mvvm实现

vue mvvm实现

Vue MVVM 实现原理 Vue.js 是一个基于 MVVM(Model-View-ViewModel)模式的框架,其核心是通过数据绑定和响应式系统实现视图与数据的自动同步。以下是 Vue 实现 M…

vue实现气泡

vue实现气泡

Vue 实现气泡效果的方法 在 Vue 中实现气泡效果可以通过 CSS 动画、第三方库或自定义组件完成。以下是几种常见实现方式: 使用纯 CSS 和 Vue 过渡 通过 Vue 的过渡系统结合 CS…

vue实现type切换

vue实现type切换

Vue 实现 Type 切换的实现方法 在 Vue 中实现 Type 切换功能可以通过动态组件、条件渲染或路由切换等方式实现。以下是几种常见方法: 使用 v-if 或 v-show 条件渲染 通过绑…

vue实现rem适配

vue实现rem适配

Vue 项目中实现 REM 适配 REM(Root EM)是一种基于根元素(html)字体大小的相对单位,常用于移动端适配。以下是在 Vue 项目中实现 REM 适配的详细方法。 安装 postcs…

vue实现图片取色

vue实现图片取色

Vue 实现图片取色功能 使用 Canvas API 提取颜色 在 Vue 项目中,可以通过 Canvas API 实现图片取色功能。创建一个组件,利用 ref 获取图片元素并绘制到 Canvas 上…