# 文件下载
# MiMe-Type
通过设置header中的Content-Disposition,指示响应头回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。
//
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"
Content-Disposition: form-data
Content-Disposition: form-data; name="fieldName"
Content-Disposition: form-data; name="fieldName"; filename="filename.jpg"
2
3
4
5
6
7
文件流下载: 比如 pdf 或者 Excel时,一般是直接点击一个连接就可以直接下载,这一般是文件流的下载方式。
通过代码设置
Response.AppendHeader("Content-Disposition","attachment;filename=FileName.txt");
通过nginx设置
https://blog.csdn.net/u011519550/article/details/104419016
location ~ ^/file {
if ($request_filename ~* ^.*?\.(txt|doc|pdf)$){
add_header Content-Disposition: 'attachment';
add_header Content-Type application/octet-stream;
}
root /home/wangjinyu;
2
3
4
5
6
# GET下载
let url = xxxx.action?a=xx&b=yy;
window.location.href = url;
// 或者
window.open(url, '_self')
2
3
4
# POST下载(form表单)
form表单下载
https://www.cnblogs.com/shengmo/p/10812481.html
// 导出excel
postExcelFile(params, url) {
//params是post请求需要的参数,url是请求url地址
var form = document.createElement('form')
form.style.display = 'none'
form.action = url
form.method = 'post'
document.body.append(form)
// 动态创建input并给value赋值
for (var key in params) {
var input = document.createElement('input')
input.type = 'hidden'
input.name = key
input.value = params[key]
form.appendChild(input)
}
form.submit()
form.remove()
}
//调用
this.postExcelFile({ currentPage: 2, pageSize: 20 }, 'url/xxxxxxx/')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
form表单无法添加Request Header,如涉及到请求头,需要使用Ajax
# 创建a标签下载
const downloadFile = async (fileName: string) => {
const blob = await getFileBlob(fileName);
if (blob) {
// 创建一个隐藏的 <a> 标签来触发下载
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = fileName.split('/').pop() || fileName; // 获取文件名
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href); // 释放内存
} else {
alert(`无法下载文件 ${fileName}`);
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Ajax通过二进制流下载文件
https://blog.csdn.net/weixin_43487782/article/details/109604950
URL.createObjectURL()静态方法会创建一个DOMString(opens new window),其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的document(opens new window) 绑定。这个新的URL 对象表示指定的File(opens new window) 对象或Blob(opens new window) 对象。createObjectURL()支持传入File(opens new window) 对象、Blob(opens new window) 对象或者MediaSource(opens new window) 对象(媒体资源)。注意:URL.createObjectURL()创建的对象使用完成后,即下载后可以通过URL.revokeObjectURL()移除该对象,释放内存。理论上讲dom销毁时,URL.createObjectURL()创建的对象也会随之销毁,我们可以不必手动销毁。但当页面有类似表格形式的文件列表时,下载完文件立即手动销毁对象无疑是最好的选择。
async function qualityExport() {
let res = await getQualityExport()
this.downloadFile(
res.data,
moment().format('YYYYMMDDHHmm'),
'application/vnd.ms-excel;charset=utf-8'
)
}
/**
* @param {ArrayBuffer|Blob} data 二进制数据
* @param {String} fileName 文件名
* @param {String} mimeType 文件mime类型
*/
function downloadFile(data, fileName, mimeType) {
let blob = new Blob([data], {
type: mimeType,
})
let URL = window.URL || window.webkitURL
let objectUrl = URL.createObjectURL(blob)
let a = document.createElement('a')
a.href = objectUrl // 文件流生成的url
a.download = `${fileName}.xlsx` // 文件名
document.body.appendChild(a)
a.click()
a.remove()
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
blob遇到的坑
axios封装时没有处理res.data为二进制数据时的状况,在响应拦截器加上二进制数据的判断,原样返回res
if (Object.prototype.toString.call(data.data) === '[object ArrayBuffer]') {
return data
}
// or
if (data.headers['content-type'] === 'application/vnd.ms-excel;charset=utf-8') {
return data
}
2
3
4
5
6
7
# Blob、ArrayBuffer和Buffer
# Blob
new Blob( array, options );
- array 是一个由
ArrayBuffer(opens new window),ArrayBufferView(opens new window),Blob(opens new window),DOMString(opens new window) 等对象构成的Array(opens new window) ,或者其他类似对象的混合体,它将会被放进Blob(opens new window)。DOMStrings会被编码为UTF-8。 - options是一个可选的
BlobPropertyBag字典,它可能会指定如下两个属性:type,默认值为"",它代表了将会被放入到blob中的数组内容的MIME类型。endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个:"native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者"transparent",代表会保持blob中保存的结束符不变。
https://zhuanlan.zhihu.com/p/97768916
# ArrayBuffer是原始的二进制数据缓冲区
# Buffer和Stream
https://zhuanlan.zhihu.com/p/31355139
https://segmentfault.com/a/1190000011968267
# 问题
ajax调下载接口后返回到数据如下
正常应该返回一个ArrayBuffer
原因: 二进制流下载,后端返回的Response Content-Type 需要是 APPLICATION/OCTET-STREAM;。
如果返回的是application/vnd.ms-excel;就会出现上述问题