使用a标签下载文件

引言

HTML中 <a> 元素(或称 元素)可以通过它的 href 属性创建通向其他网页、文件、电子邮件地址、同一页面内的位置或任何其他 URL 的超链接。

<a> 中的内容应该指明链接的目标。如果存在 href 属性,当 <a> 元素聚焦时按下回车键就会激活它。

本文主要讲解如何通过a标签来下载文件。

download属性

浏览器将链接的 URL 视为下载资源。可以使用或不使用 filename 值:

  • 如果没有指定值,浏览器会从多个来源决定文件名和扩展名:

    • Content-DispositionHTTP 标头。
    • URL的最后一段。
    • 媒体类型。来自 Content-Type 标头,data: URL的开头,或 blob: URL 的 Blob.type
  • filename:决定文件名的值。/\ 被转化为下划线(_)。文件系统可能会阻止文件名中其他的字符,因此浏览器会在必要时适当调整文件名。

备注:

  • download 只在同源 URLblob:data: 协议起作用。
  • 浏览器对待下载的方式因浏览器、用户设置和其他因素而异。在下载开始之前,可能会提示用户,或者自动保存文件,或者自动打开。自动打开要么在外部应用程序中,要么在浏览器本身中。
  • 如果 Content-Disposition 标头的信息与 download 属性不同,产生的行为可能不同:
  • 如果文件头指定了一个 filename,它将优先于 download 属性中指定的文件名。
  • 如果标头指定了 inline 的处置方式,Chrome 和 Firefox 会优先考虑该属性并将其视为下载资源。旧的 Firefox 浏览器(版本 82 之前)优先考虑该标头,并将内联显示内容。

下载方式

1. 直接使用a标签的href属性指定文件的URL

可以在a标签中使用href属性指定文件的URL,点击链接时会直接下载文件。

html 复制代码
<a href="file_url">Download</a>

优点:简单易用,只需在a标签中指定文件的URL即可。

缺点:无法控制下载文件的名称和保存位置。

2. 使用download属性指定下载文件的名称

可以在a标签中使用download属性指定下载文件的名称,点击链接时会将文件以该名称保存到本地。

html 复制代码
<a href="file_url" download="file_name">Download</a>

优点:可以控制下载文件的名称。

缺点:无法控制下载文件的保存位置。

3. 将文件数据转为Blob进行下载

当需要将文件数据转为Blob或Base64进行下载时,可以使用以下方法:

1. 将文件数据转为Blob进行下载

javascript 复制代码
function downloadFile(data, filename, type) {
  const blob = new Blob([data], { type: type });
  const url = URL.createObjectURL(blob);

  const link = document.createElement('a');
  link.href = url;
  link.download = filename;

  document.body.appendChild(link);
  link.click();

  document.body.removeChild(link);
  URL.revokeObjectURL(url);
}

function fileToBlob(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onloadend = () => {
      resolve(new Blob([reader.result], { type: file.type }));
    };

    reader.onerror = reject;

    reader.readAsArrayBuffer(file);
  });
}

// 使用示例
const fileData = ...; // 文件数据
const fileName = 'example.txt';
const fileType = 'text/plain';

fileToBlob(fileData).then(blob => {
  downloadFile(blob, fileName, fileType);
});

首先,我们定义了一个名为downloadFile的函数,它接受三个参数:文件数据(data),文件名(filename)和文件类型(type)。 在函数内部,我们使用Blob构造函数将文件数据和类型传递给它,从而创建一个Blob对象。然后,我们使用URL.createObjectURL()方法创建一个URL,该URL指向Blob对象。 接下来,我们创建一个<a>元素,并设置其href属性为之前创建的URL,并将下载属性设置为指定的文件名。然后将该元素添加到文档的body中。 最后,我们模拟用户点击该链接进行下载,并在完成后清理相关资源。

在使用时,我们首先调用fileToBlob函数将文件数据转换为Blob对象。该函数返回一个Promise对象,在Promise的resolve回调中返回了转换后的Blob对象。 然后,在Promise的回调中调用了downloadFile函数来进行下载。

2. 将文件数据转为Base64进行下载

javascript 复制代码
function downloadBase64File(base64Data, filename, type) {
  const byteCharacters = atob(base64Data);
  const byteArrays = [];

  for (let i = 0; i < byteCharacters.length; i++) {
    byteArrays.push(byteCharacters.charCodeAt(i));
  }

  const blob = new Blob([new Uint8Array(byteArrays)], { type: type });
  const url = URL.createObjectURL(blob);

  const link = document.createElement('a');
  link.href = url;
  link.download = filename;

  document.body.appendChild(link);
  link.click();

  document.body.removeChild(link);
}

function fileToBase64(file) {
 return new Promise((resolve, reject) => {
   const reader = new FileReader();

   reader.onloadend = () => {
     resolve(reader.result.split(',')[1]);
   };

   reader.onerror = reject;

   reader.readAsDataURL(file);
 });
}

// 使用示例
const fileData = ...; // 文件数据
const fileName = 'example.txt';
const fileType = 'text/plain';

fileToBase64(fileData).then(base64Data => {
  downloadBase64File(base64Data, fileName, fileType);
});

首先,我们定义了一个名为downloadBase64File的函数,它接受三个参数:Base64字符串(base64Data),文件名(filename)和文件类型(type)。 在函数内部,我们首先将Base64字符串解码为字节数组,并将其存储在byteArrays数组中。然后,我们使用这些字节数组创建一个Blob对象,并使用URL.createObjectURL()方法创建一个URL。 接下来,我们创建一个<a>元素,并设置其href属性为之前创建的URL,并将下载属性设置为指定的文件名。然后将该元素添加到文档的body中。 最后,我们模拟用户点击该链接进行下载,并在完成后清理相关资源。

在使用时,我们首先调用fileToBase64函数将文件数据转换为Base64字符串。该函数返回一个Promise对象,在Promise的resolve回调中返回了转换后的Base64字符串。 然后,在Promise的回调中调用了downloadBase64File函数来进行下载。

总结

您可以根据需要选择将文件数据转为Blob或Base64进行下载。如果您已经有文件数据,可以使用fileToBlob函数将其转为Blob对象并进行下载。如果您希望将文件数据转为Base64进行下载,可以使用fileToBase64函数将其转为Base64字符串,并使用downloadBase64File函数进行下载。

相关推荐
90后的晨仔16 分钟前
在macOS上无缝整合:为Claude Code配置魔搭社区免费API完全指南
前端
沿着路走到底1 小时前
JS事件循环
java·前端·javascript
子春一21 小时前
Flutter 2025 可访问性(Accessibility)工程体系:从合规达标到包容设计,打造人人可用的数字产品
前端·javascript·flutter
白兰地空瓶1 小时前
别再只会调 API 了!LangChain.js 才是前端 AI 工程化的真正起点
前端·langchain
jlspcsdn2 小时前
20251222项目练习
前端·javascript·html
行走的陀螺仪2 小时前
Sass 详细指南
前端·css·rust·sass
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ3 小时前
React 怎么区分导入的是组件还是函数,或者是对象
前端·react.js·前端框架
LYFlied3 小时前
【每日算法】LeetCode 136. 只出现一次的数字
前端·算法·leetcode·面试·职场和发展
子春一23 小时前
Flutter 2025 国际化与本地化工程体系:从多语言支持到文化适配,打造真正全球化的应用
前端·flutter
QT 小鲜肉3 小时前
【Linux命令大全】001.文件管理之file命令(实操篇)
linux·运维·前端·网络·chrome·笔记