JavaScript 提供了多种方式来实现文件下载。不同的需求和环境下可能需要不同的方法,以下是 14 种常见的 JavaScript 实现文件下载的方法总结,涵盖了浏览器端的下载方式、动态生成文件、处理二进制数据等。

1. 使用 <a> 标签的 download 属性

适用场景:简单的静态文件下载。

<a href="path/to/file.pdf" download="example.pdf">Download</a>

说明

  • href:文件的路径。
  • download:指定下载文件的名称。
  • 适用于已知文件路径的情况。

2. 使用 Blob 和 URL.createObjectURL()

适用场景:下载动态生成的文件,如用户输入内容生成的文本文件。

const content = 'Hello, World!';
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);

const a = document.createElement('a');
a.href = url;
a.download = 'hello.txt';
a.click();

URL.revokeObjectURL(url); // 释放 URL 对象

说明

  • 使用 Blob 可以动态创建文件内容。
  • URL.createObjectURL 用于创建一个可以下载的临时 URL。

3. 使用 FileSaver.js 库

适用场景:需要在浏览器中保存文件,特别是对于大文件的下载。

// 使用 FileSaver.js 库
const content = 'Hello, World!';
const blob = new Blob([content], { type: 'text/plain' });
saveAs(blob, 'hello.txt');

说明

  • FileSaver.js 库可以让文件保存变得更加简单,支持多种浏览器。

4. 使用 data: URL

适用场景:将数据嵌入 URL 中直接下载,适用于小文件。

const content = 'Hello, World!';
const dataUrl = `data:text/plain;charset=utf-8,${encodeURIComponent(content)}`;

const a = document.createElement('a');
a.href = dataUrl;
a.download = 'hello.txt';
a.click();

说明

  • 将文件内容嵌入 URL 中,不需要服务器存储文件。
  • 适合小文件(一般小于 2MB)。

5. 使用 XMLHttpRequest 和 Blob 下载文件

适用场景:从服务器下载文件并保存到本地。

const xhr = new XMLHttpRequest();
xhr.open('GET', 'path/to/file.pdf', true);
xhr.responseType = 'blob';

xhr.onload = function() {
  const blob = xhr.response;
  const url = URL.createObjectURL(blob);
  
  const a = document.createElement('a');
  a.href = url;
  a.download = 'file.pdf';
  a.click();
  
  URL.revokeObjectURL(url);
};

xhr.send();

说明

  • 使用 XMLHttpRequest 来请求文件内容。
  • responseType = 'blob' 用于获取二进制数据。

6. 使用 fetch() API 下载文件

适用场景:从服务器异步获取文件并保存。

fetch('path/to/file.pdf')
  .then(response => response.blob())
  .then(blob => {
    const url = URL.createObjectURL(blob);
    
    const a = document.createElement('a');
    a.href = url;
    a.download = 'file.pdf';
    a.click();
    
    URL.revokeObjectURL(url);
  })
  .catch(console.error);

说明

  • 使用 fetch() API 来简化网络请求,支持 Promise。

7. 使用 iframe 模拟下载

适用场景:模拟文件下载,尤其是在跨域情况下。

const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = 'path/to/file.pdf';
document.body.appendChild(iframe);

说明

  • 通过创建隐藏的 iframe,可以触发浏览器的默认下载行为。

8. 使用 form 标签和 POST 请求下载文件

适用场景:需要通过 POST 请求下载文件,传递参数。

const form = document.createElement('form');
form.method = 'POST';
form.action = 'path/to/download';

const input = document.createElement('input');
input.type = 'hidden';
input.name = 'param';
input.value = 'value';
form.appendChild(input);

document.body.appendChild(form);
form.submit();
document.body.removeChild(form);

说明

  • 使用 POST 请求来发送参数并触发文件下载。

9. 使用 window.location 进行下载

适用场景:简单的下载请求,适合 GET 请求。

window.location.href = 'path/to/file.pdf';

说明

  • 简单地改变 window.location 跳转到文件 URL,浏览器会自动处理下载。

10. 使用 WebSocket 进行下载(适合实时下载)

适用场景:需要实时获取大文件或流数据并保存。

const ws = new WebSocket('ws://example.com/file-stream');
ws.onmessage = (event) => {
  const blob = event.data;
  const url = URL.createObjectURL(blob);
  
  const a = document.createElement('a');
  a.href = url;
  a.download = 'file.dat';
  a.click();
  
  URL.revokeObjectURL(url);
};

说明

  • 使用 WebSocket 实时传输文件,适用于长时间连接和流式数据下载。

11. 使用 download 属性与数据 URL 结合

适用场景:下载较小的文本或图像文件。

const content = 'Hello, World!';
const encodedUri = encodeURI('data:text/plain;charset=utf-8,' + content);
const a = document.createElement('a');
a.setAttribute('href', encodedUri);
a.setAttribute('download', 'hello.txt');
a.click();

说明

  • 将数据通过 data: URL 嵌入到 href 中,并使用 download 属性触发下载。

12. 使用 Window.open() 下载文件

适用场景:浏览器窗口中打开文件进行下载。

window.open('path/to/file.pdf', '_blank');

说明

  • 使用 window.open() 打开文件,浏览器会根据设置下载或显示文件。

13. 使用 Response 和 Blob 结合下载

适用场景:处理 HTTP 响应并下载文件。

fetch('path/to/file.pdf')
  .then(response => response.blob())
  .then(blob => {
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = 'file.pdf';
    link.click();
  })
  .catch(err => console.error(err));

说明

  • 通过 Response 对象获取文件内容并使用 Blob 下载。

14. 使用 Content-Disposition HTTP 头进行服务器端下载

适用场景:后端设置 Content-Disposition 头,强制浏览器下载文件。

Content-Disposition: attachment; filename="file.pdf"

说明

  • 这种方法是在服务器端设置 Content-Disposition: attachment 头来强制浏览器下载文件。

总结

  1. 基础方法:利用 <a> 标签的 download 属性、data: URL 和 Blob 是最简单的文件下载方式。
  2. 高级方法:如 fetchXMLHttpRequestWebSocket 可以用于动态或流式数据的下载。
  3. 第三方库:使用如 FileSaver.js 等库来简化复杂的下载操作,尤其是处理大文件时。

这些方法可以根据不同的需求选择使用,确保用户体验和性能的平衡。