前端文件下载全攻略:从单文件到批量下载,哪种方法最优?

小张是一名刚入职的前端开发工程师,某天,他的领导给他布置了一个看似简单的任务:

让用户能够通过文件链接下载多个文件

小张信心满满,觉得这不过是个小问题。然而,当他真正动手时,才发现这个需求并不简单。不同的下载方式各有优缺点,甚至有些方法会带来意想不到的问题,他决定一一尝试,探索最优解。

方案一:window.open------简单粗暴,但会打开新标签页

小张首先想到的是 window.open(url),它可以让浏览器直接打开下载链接。

js 复制代码
window.open('https://example.com/file.pdf');

优点

  • 代码简单,直接调用即可。
  • 适用于单个文件的下载。

缺点

  • 每次下载都会打开一个新的浏览器标签页,影响用户体验。
  • 部分浏览器可能会拦截 window.open,导致下载失败。

方案二:window.location.href 简单有效,但不能同时下载多个文件

小张发现,window.location.href 也可以实现下载,且不会打开新标签页。

js 复制代码
window.location.href = 'https://example.com/file.pdf';

优点

  • 适用于单文件下载。
  • 不会像 window.open 那样打开新页面。

缺点

  • 无法循环下载多个文件 。如果连续多次赋值 window.location.href,后一个请求会覆盖前一个,导致只能下载最后一个文件。

方案三:iframe 支持多文件下载,但无法监听完成状态

为了让多个文件能够顺利下载,小张尝试用 iframe

js 复制代码
function downloadFile(url) {
  const iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  iframe.src = url;
  document.body.appendChild(iframe);
  setTimeout(() => {
    document.body.removeChild(iframe);
  }, 5000); // 延迟移除 iframe,防止影响下载
}

优点

  • 适用于多文件下载。

缺点

  • iframe 无法监听文件下载是否完成。
  • 需要在合适的时机移除 iframe,否则可能会影响页面性能。

方案四:fetch + blob------最优雅的下载方式

小张最终发现,fetch 可以获取文件数据,再通过 Blob 处理并使用 a 标签下载。

js 复制代码
async function downloadFile(url, fileName) {
  const response = await fetch(url);
  if (!response.ok) throw new Error('Download failed');
  const blob = await response.blob();
  const blobUrl = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = blobUrl;
  a.download = fileName;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(blobUrl);
}

function download(fileList){
   for(const file of fileList) {
     await downloadFile(file.url,file.name)
   }
}

优点

  • 不会打开新标签页。
  • 可以同时下载多个文件。
  • 适用于现代浏览器,兼容性较好。

缺点

  • 需要处理异步 fetch 请求。
  • 服务器必须支持跨域资源共享(CORS),否则 fetch 请求会失败。
  • 多次文件下载会导致多个浏览器下载图标 :每次调用 a.click() 时,浏览器都会显示一个下载图标,影响用户体验。

方案五:jsZip 打包多个文件为 ZIP 下载------避免多次下载图标

为了进一步优化方案四,避免浏览器每次下载时显示多个下载图标,小张决定使用 jsZip 插件将多个文件打包成一个 ZIP 文件下载。

js 复制代码
import JSZip from 'jszip';

async function downloadFilesAsZip(files) {
  const zip = new JSZip();
  // 循环遍历多个文件,获取每个文件的数据
  for (const file of files) {
    const response = await fetch(file.url);
    if (!response.ok) throw new Error(`Failed to fetch ${file.name}`);
    const blob = await response.blob();
    zip.file(file.name, blob); // 将文件添加到 ZIP 包中
  }

  // 生成 ZIP 文件并触发下载
  zip.generateAsync({ type: "blob" })
    .then(function(content) {
      const a = document.createElement('a');
      const blobUrl = URL.createObjectURL(content);
      a.href = blobUrl;
      // 给压缩包设置下载文件名
      a.download = 'files.zip';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      // 释放 URL 对象
      URL.revokeObjectURL(blobUrl);
    });
}

优点

  • 提升用户体验:用户下载一个压缩包后,只需解压就可以获取所有文件,避免了多次点击和等待的麻烦。
  • 适用于多文件下载:非常适合需要批量下载的场景。

缺点

  • 浏览器对大文件的支持:如果要下载的文件非常大,或者文件总大小很大,可能会导致内存消耗过高,甚至在浏览器中崩溃。
  • 下载速度受限于压缩处理:打包文件为 ZIP 需要时间,尤其是文件较多时,会稍微影响压缩的速度,只适用于文件不是很大且数量不是很多的时候

结语:小张的最终选择

经过一番探索,小张最终选择了 jsZip 打包文件的方案,因为它不仅解决了多个文件下载时图标显示的问题,还提高了用户体验,让下载更加流畅,没有哪个方案比另外一个方案好,只有最适合的方案,根据实际的场景能满足需求最优解就是最好的。

相关推荐
牧艺30 分钟前
cos-design v3.0:从 15 个 Demo 到 49 个组件的视觉特效库
前端·视觉设计
lichenyang45332 分钟前
ASCF 架构升级总览:WebRuntimePage 为什么要变薄
前端
道友可好33 分钟前
从今天开始:你的第一个 Harness Engineering 实践
前端·人工智能·后端
Linsk35 分钟前
组件 = 模板 + 业务逻辑
java·前端·vue.js
二月龙1 小时前
移动端 H5 页面开发:响应式适配 + 低版本兼容实战指南
前端
小强19881 小时前
HTML5 新表单全解:日期、手机号、颜色选择器
前端
妙码生花1 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(二):目录结构、初始化 GIT、设计并开发配置系统
前端·后端·go
鱼人1 小时前
HTML5 本地存储终极指南
前端
超绝大帅哥1 小时前
React的Fiber是什么? Vue为什么不需要Fiber ?
前端
yingyima2 小时前
正则表达式分组与捕获:凌晨3点服务器报警的解决方案
前端