怎么指定下载文件名?

在浏览器中下载文件是一个比较常见的操作,那么你知道在前端怎么去给要下载的文件指定一个文件名吗?

1. 指定 Content-Disposition 响应头

通过设置响应头中的 Content-Disposition 字段,可以来指定下载文件的文件名。我们需要将 Content-Disposition 设置为 attachment,并在 filename 参数中指定所需的文件名。

比如我需要将下载文件的文件名设置为 file.txt,可以这样设置:

res.setHeader('Content-Disposition', 'attachment; filename=file.txt');

2. 通过 a 标签的 download 属性

除了上面需要在后端设置响应头的方式之外,还可以通过在前端给 a 标签添加 download 属性来实现。

例如如下链接,链接指向的是一个图片,当点击下载时,会将图片下载到本地,并且文件名为 baidu.png

<a href="https://www.baidu.com/img/bd_logo1.png" download="baidu.png">下载</a>

当然,我们还可以通过使用 Blob 来实现相同的下载功能,其方式和上面使用 a 标签的方式类似。

function downloadFile(url, filename) {
  fetch(url)
    .then((response) => response.blob())
    .then((blob) => {
      const link = document.createElement('a');
      link.href = URL.createObjectURL(blob);
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    });
}

// 例如:下载名为example.pdf的PDF文件
downloadFile('http://example.com/example.pdf', 'newfilename.pdf');

都是通过 download 属性来指定下载文件的文件名,不过,这种方式可以为下载提供更多的可能性,比如可以实现下载的进度条,断点续传等等,这里不再展开。

优先级

那么,上面两种方式都可以实现下载文件的文件名,假如我同时设置了这两种方式,哪种方式的优先级更高呢?

一般而言,download 的优先级会更高一点,不过不同的浏览器可能会有不同的实现,在 MDN 中是这么说的。

  • filenamefilename* 两个参数同时出现的情况下,Firefox 5 可以更好地处理 Content-Disposition HTTP 响应标头。它会遍历所有提供的名称,假如 filename* 存在的话,就采用它的值,即使 filename 更靠前。之前的版本会采用出现在前面的参数的值,导致有更合适的名称而不被使用。参见 Firefox bug 588781。
  • Firefox 82(及更高版本)和 Chrome 优先考虑 HTML <a> 元素的 download 属性,而不是 Content-Disposition:inline 参数(对于同源 URL)。早期的 Firefox 版本优先考虑标头,并会内联显示内容。

所以,为了避免不同浏览器上的行为表现不一致,最好只使用其中一种方式。

如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注