需求描述
批量接管实例功能需要增加一个离线检查工具下载功能,该工具为一个二进制文件。点击下载可下载该二进制文件到本地。
问题描述
本身项目里已经封装了一个工具函数用于文件下载:
public downloadByCreateElementA(fileStream: any, fileName?: string) {
const url = window.URL.createObjectURL(new Blob([fileStream]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName ? fileName : 'file');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
//组件中调用
const downloadOfflineCheckTool = () => {
MysqlService.DownloadMysqlTakeoverInspectTool({
responseType: 'blob'
})
.then((res) => {
Download.downloadByCreateElementA(res, 'mysql_takeover_inspect_tool');
})
.catch((err) => {
showRequestError(err.data);
});
};
自测发现,此时可以下载到文件,但下载到本地的文件均以.txt结尾。
解决方法
给downloadByCreateElementA新增可选参数config,指定type为application/octet-stream
const downloadOfflineCheckTool = () => {
MysqlService.DownloadMysqlTakeoverInspectTool({
responseType: 'blob',
})
.then((res) => {
Download.downloadByCreateElementA(res, 'mysql_takeover_inspect_tool', {
type: 'application/octet-stream',
});
})
};
public downloadByCreateElementA(
fileStream: any,
fileName?: string,
config?: { type: string }
) {
let blob: Blob;
if (!!config) {
blob = new Blob([fileStream], config);
} else {
blob = new Blob([fileStream]);
}
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName ? fileName : 'file');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
原因
相对原本的代码,修改后的代码只是在创建Blob对象时,指定了type参数为application/octet-stream,而不是默认的空字符串。如果在设置download的时候没有强制指定文件后缀名,浏览器可能会根据文件内容尝试猜测文件类型并添加默认的扩展名
MIME type
在了解Blob对象之前需要先理解什么是MIME type。MIME type是meida Type的子集,由媒体类型和子类型组成,中间由斜杠分隔。比如text/html。MIME type是用来告诉web浏览器如何处理媒体内容,常见类型如下:
| type | 处理方式 |
|---|---|
| text/plain | 普通文本 |
| text/html | 普通网页 |
| text/css | 级联样式表 |
| text/javascript | 脚本 |
| application/octet-stream | 下载文件 |
| application/x-java-applet | Java applets |
| application/pdf | pdf文档 |
对于空字符串的处理方式取决于具体的应用、框架或者服务器,比如:
- 服务器将其解释为默认的mime type
- 将其看做错误,返回带有错误码的响应
- 根据文件扩展名或者对内容结构进行解析,自动检测mime type
- 直接忽略
Blob对象
Blob对象代表一个类文件对象,具有以下特征:
- 一旦创建就不可修改。
- 包括文本和二进制数据等任意类型的数据,可以用来处理纯文本、json、图像、视频等类型的原始数据
- 可以转换为
ReadableStream用于数据操作
Blob构造函数
语法:
new Blob(blobParts,{
type?:(mimeType),
endings?:(transparent|native)//不推荐
}) //返回新的Blob对象
blobParts参数不仅仅指数组,而是指所有的可迭代对象(ArrayBuffer,TypedArray,DataView,Blob,string,或者混合体)。而type参数指的是将会被存储到blob中的数据的MIME类型。
总结:
如果没有在download中指定下载文件的后缀,就必须在创建Blob对象的时候指定type