目前JS下载文件的方式有两种:
// 第一种,直接a标签下载,download修改文件名不会生效,浏览器会有下载文件的交互,大文件体验好
const a = document.createElement('a');
a.href = downloadUrl;
a.download = "new_filename.txt"; // 设置文件名
a.click();
a.remove();
// 第二种,需要等blob下载完之后才能改名,大文件需要等待,体验差
const result = await axios(path, {
method: 'get',
responseType: 'blob',
});
const blob = new Blob([result.data]);
const a = document.createElement('a');
a.download = "new_filename.txt"; // 设置文件名
a.href = URL.createObjectURL(blob);
a.click();
URL.revokeObjectURL(a.href);
a.remove();
为了更好的用户体验,我们肯定是要选择第一种,那有什么办法可以既保持用户体验的同时又可以修改文件名呢。
下面先介绍一个HTTP Response Header
1. Content-Disposition
Content-Disposition
是 HTTP 头部中的一个字段,它指示了如何处理响应的内容。这个头部字段通常用于告诉浏览器如何处理服务器发送的文件下载,特别是如何处理文件的文件名和下载行为。
它的值可以有几种不同的形式:
- inline:指示浏览器直接在页面上显示响应的内容,而不是将其下载到本地计算机。
- attachment:指示浏览器应该将响应的内容作为附件下载到本地计算机。
- filename=filename.ext:指示下载的文件名为 filename.ext。浏览器将使用这个文件名来保存下载的文件。如果这个参数不存在,那么浏览器通常会使用最后一个斜杠后的部分作为文件名。
例如,一个典型的 Content-Disposition
头部可能是这样的:
Content-Disposition: attachment; filename="example.txt"
这个头部告诉浏览器应该将响应的内容作为附件下载,并且文件名应该为 “example.txt”。
如果我们可以修改AWS S3 、阿里OSS的对象存储URL Response headers 中的 Content-Disposition
,那么我们可以采用第一种下载的方式,并且重命名资源了。
2. 具体实现
那么查找文档可以发现,AWS S3 和 阿里 OSS 都支持通过签名的方式修改Content-Disposition。
AWS S3:
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
export const downloadAWSFile = async (path: string, filename: string) => {
const client = new S3Client({
region: S3_REGION, // 区域
credentials: {}, // 验证信息
});
const { GetObjectCommand } = await import('@aws-sdk/client-s3');
const command = new GetObjectCommand({
Bucket,
Key,
ResponseContentDisposition: `attachment; filename=${filename}`,
});
return getSignedUrl(client, command);
};
阿里 OSS:
import OSS from "ali-oss";
export const downloadOSSFile = async (path: string, filename: string) => {
const client = new OSS({
accessKeyId,
accessKeySecret,
bucket,
region,
});
const { Key } = getOSSInfoFromUrl(path);
const response = {
'content-disposition': `attachment; filename=${encodeURIComponent(filename)}`,
};
return client.signatureUrl(Key, { response });
};
原文链接:https://juejin.cn/post/7356055901495328777 作者:yasuomang