下载
一. 下载固定文档
固定文档后端通常会返回一个文档链接,可以使用 window.open() 直接下载;
二. 下载动态文档
- 有时是动态文档,此时后端会返回一个文件流,此时前端需要做一些特殊处理进行下载并获取文件名。
// 处理模版文件流下载
const downloading = ref(false);
const downloadFile = async () => {
const res: any = await api({
id: id.value,
name: name.value,
});
try {
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const objectUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = objectUrl;
a.download = '这是一个固定的文件名';
document.body.appendChild(a); // 部分浏览器要求a元素添加在DOM中才能正常工作
a.click();
URL.revokeObjectURL(objectUrl);
document.body.removeChild(a);
} catch (e: any) {
LiMessage.error('下载失败,请联系管理员。报错信息:', e);
}
};
- 获取动态文件名后端会在content-disposition中返回,此时需要单独处理,如果使用的是非最新脚手架,response会被封装起来,需要在request.ts的拦截器中放开
注意: 如果想在浏览器中通过 JavaScript 获取 `Content-Disposition` 字段,服务器需要在响应中设置`Access-Control-Expose-Headers` 响应头,并包括 `Content-Disposition` ,这样前端代码才能访问到它。
例如,后端可以设置以下的响应头: Access-Control-Expose-Headers: Content-Disposition
// request.ts response 拦截器
request.interceptors.response.use(
(response) => {
if (response.config.rawResponse) return response;
return response.data; //返回请求头信息
},
(error) => {
if (env !== 'prod') {
console.error('[Response Interceptors Error]: ', error); // for debug
}
switch (error.response.status) {
case 401:
break;
case 400: // 如果响应中的 http code 为 400,那么就弹出一条错误提示给用户
case 500:
return LiMessage({
message: error.response.data.message,
type: 'error',
duration: 1000,
});
default:
}
return Promise.reject(error);
},
);
接口api特殊处理
export function getApi(
query: Cli.Request.query,
configs?: RequestConfig,
isMock?: boolean,
): RequestPromise<Cli.Response.type> {
return request.get(
`${ apiPrefix.api}/api`,
{
...configs,
params: query,
responseType: 'blob',
rawResponse: true,
},
);
}
- 在response.header中获取文件名并处理
如果文件名类似: "Excel-ÀíÏëLÕýʽ°æ-Ä£°æ-20240110095859.xlsx" 前端将无法进行解码获取到正确文件名,这通常是因为前后端字符编码不一致,需要后端用url转码处理一下,此时获取到的文件名为filename="Excel-%E7%90%86%E6%83%B3L9%E6%AD%A3%%89%88SKU%E6%A8%A1%E7%89%88-20240110103630.xlsx";之后就可以进行专门解析
try {
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const objectUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = objectUrl;
// 解析文件名,假设contentDisposition是响应头中获取到的Content-Disposition
let contentDisposition = res.headers['content-disposition'];
let fileName = contentDisposition.match(/filename\*?=(UTF-8'')?([^;]+)/)[2];
if (fileName.startsWith('"') && fileName.endsWith('"')) { fileName = fileName.substring(1, fileName.length - 1); // 去掉两端的双引号
}
fileName = decodeURIComponent(fileName); // 对文件名进行解码
a.download = fileName; document.body.appendChild(a); // 部分浏览器要求a元素添加在DOM中才能正常工作 a.click(); URL.revokeObjectURL(objectUrl); document.body.removeChild(a);
} catch (e: any) {
LiMessage.error('下载失败,请联系管理员。报错信息:', e);
}
附录
MIME类型汇总:常见 MIME 类型列表 - HTTP | MDN
两种主要的 MIME 类型在默认类型中扮演了重要的角色:
text/plain表示文本文件的默认值。一个文本文件应当是人类可读的,并且不包含二进制数据。application/octet-stream表示所有其他情况的默认值。一种未知的文件类型应当使用此类型。浏览器在处理这些文件时会特别小心,试图防止、避免用户的危险行为。
IANA 是 MIME 媒体类型的官方注册机构,并维护了官方所有 MIME 类型的列表。下面的表格列出了 Web 上的一些重要 MIME 类型:
| 扩展名 | 文档类型 | MIME 类型 |
|---|---|---|
| .aac | AAC 音频 | audio/aac |
| .abw | AbiWord 文档 | application/x-abiword |
| .apng | 动态可移植网络图形(APNG)图像 | image/apng |
| .arc | 归档文件(嵌入多个文件) | application/x-freearc |
| .avif | AVIF 图像 | image/avif |
| .avi | AVI:音频视频交织文件格式(Audio Video Interleave) | video/x-msvideo |
| .azw | Amazon Kindle 电子书格式 | application/vnd.amazon.ebook |
| .bin | 任何二进制数据类型 | application/octet-stream |
| .bmp | Windows OS/2 位图 | image/bmp |
| .bz | BZip 归档 | application/x-bzip |
| .bz2 | BZip2 归档 | application/x-bzip2 |
| .cda | CD 音频 | application/x-cdf |
| .csh | C-Shell 脚本 | application/x-csh |
| .css | 层叠样式表(CSS) | text/css |
| .csv | 逗号分隔值(CSV) | text/csv |
| .doc | Microsoft Word | application/msword |
| .docx | Microsoft Word(OpenXML) | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
| .eot | MS 嵌入式 OpenType 字体 | application/vnd.ms-fontobject |
| .epub | 电子出版(EPUB) | application/epub+zip |
| .gz | GZip 压缩归档 | application/gzip |
| .gif | 图像互换格式(GIF) | image/gif |
| .htm, .html | 超文本标记语言(HTML) | text/html |
| .ico | 图标(Icon)格式 | image/vnd.microsoft.icon |
| .ics | iCalendar 格式 | text/calendar |
| .jar | Java 归档(JAR) | application/java-archive |
| .jpeg, .jpg | JPEG 图像 | image/jpeg |
| .js | JavaScript | text/javascript (规范:HTML 和 RFC 9239) |
| .json | JSON 格式 | application/json |
| .jsonld | JSON-LD 格式 | application/ld+json |
| .mid, .midi | 音乐数字接口(MIDI) | audio/midi、audio/x-midi |
| .mjs | JavaScript 模块 | text/javascript |
| .mp3 | MP3 音频 | audio/mpeg |
| .mp4 | MP4 视频 | video/mp4 |
| .mpeg | MPEG 视频 | video/mpeg |
| .mpkg | Apple 安装包 | application/vnd.apple.installer+xml |
| .odp | 开放文档演示稿文档 | application/vnd.oasis.opendocument.presentation |
| .ods | 开放文档表格文档 | application/vnd.oasis.opendocument.spreadsheet |
| .odt | 开放文档文本文档 | application/vnd.oasis.opendocument.text |
| .oga | OGG 音频 | audio/ogg |
| .ogv | OGG 视频 | video/ogg |
| .ogx | OGG | application/ogg |
| .opus | Opus 音频 | audio/opus |
| .otf | OpenType 字体 | font/otf |
| .png | 便携式网络图形 | image/png |
| Adobe 便携式文档格式(PDF) | application/pdf | |
| .php | 超文本预处理器(Personal Home Page) | application/x-httpd-php |
| .ppt | Microsoft PowerPoint | application/vnd.ms-powerpoint |
| .pptx | Microsoft PowerPoint(OpenXML) | application/vnd.openxmlformats-officedocument.presentationml.presentation |
| .rar | RAR 归档 | application/vnd.rar |
| .rtf | 富文本格式(RTF) | application/rtf |
| .sh | 伯恩 shell 脚本 | application/x-sh |
| .svg | 可缩放矢量图形(SVG) | image/svg+xml |
| .tar | 磁带归档(TAR) | application/x-tar |
| .tif, .tiff | 标签图像文件格式(TIFF) | image/tiff |
| .ts | MPEG 传输流 | video/mp2t |
| .ttf | TrueType 字体 | font/ttf |
| .txt | 文本(通常是 ASCII 或 ISO 8859-n) | text/plain |
| .vsd | Microsoft Visio | application/vnd.visio |
| .wav | 波形音频格式 | audio/wav |
| .weba | WEBM 音频 | audio/webm |
| .webm | WEBM 视频 | video/webm |
| .webp | WEBP 图像 | image/webp |
| .woff | Web 开放字体格式(WOFF) | font/woff |
| .woff2 | Web 开放字体格式(WOFF) | font/woff2 |
| .xhtml | XHTML | application/xhtml+xml |
| .xls | Microsoft Excel | application/vnd.ms-excel |
| .xlsx | Microsoft Excel(OpenXML) | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
| .xml | XML | RFC 7303(section 4.1)推荐使用 application/xml,但有时仍会使用 text/xml。你可以将特定的 MIME 类型分配给具有 .xml 扩展名的文件,这取决于其内容的解释方式。例如,Atom 消息来源是 application/atom+xml,而 application/xml 是默认的有效值。 |
| .xul | XUL | application/vnd.mozilla.xul+xml |
| .zip | ZIP 归档 | application/zip |
| .3gp | 3GPP 音视频容器 | video/3gpp;如果不包含视频则为 audio/3gpp |
| .3g2 | 3GPP2 音视频容器 | video/3gpp2;如果不包含视频则为 audio/3gpp2 |
| .7z | 7-zip 归档 | application/x-7z-compressed |