通过浏览器自动下载。浏览器接收到二进制文件,自动转码下载。比如:window.open()
通过xhr下载。ajax请求得到的是二进制文件,只能手动转码下载。
这种需要后端配置响应参数
例子:
本地起了一个node服务,端口3000
设置了content-disposition的情况:
页面设置:
<button onclick="downImg(1)">点击下载图片</button>
<button onclick="downImg(2)">点击下载excel</button>
<script>
function downImg(type) {
if(type ===1) {
window.open(‘http://127.0.0.1:3000/img‘);
} else {
window.open(‘http://127.0.0.1:3000/api‘);
}
}
</script>
后端:
app.get(‘/img‘, (req, res) => {
res.setHeader(‘Content-Type‘, ‘image/jpeg‘);
// res.download自动设置Content-disposition
res.download(‘./public/1.jpg‘);
})
实验结果:
ie >=8 ,成功下载图片;
chrome,成功下载图片;
未设置content-disposition的情况
app.get(‘/img‘, (req, res) => {
res.setHeader(‘Content-Type‘, ‘image/jpeg‘);
let pathname = path.join(__dirname, ‘./public/1.jpg‘)
res.sendFile(pathname);
})
app.get(‘/api‘, (req, res) => {
res.setHeader(‘Content-Type‘, ‘application/vnd.ms-excel‘);
let pathname = path.join(__dirname, ‘./public/api.xlsx‘)
res.sendFile(pathname);
})
实验结果:
图片在新标签页打开
excel表自动下载了
function alabel(src, downloadName) {
// 注意,ie11还不支持es6的语法
var a = document.createElement(‘a‘);
a.target = "_blank";
a.href = src;
a.download = downloadName;
a.click();
}
function downImg() {
var url = ‘http://127.0.0.1:3000/img‘;
alabel(url, ‘1.jpg‘);
}
实验结果:
浏览器 | chrome | ie |
---|---|---|
同域 | 可以下载 | 不能下载 |
跨域 | 打开新标签页 | 不能下载 |
设置content-disposition | 可以下载 | 不能下载 |
没设置content-disposition | 可以下载 | 不能下载 |
所以a标签下载跟浏览器的兼容性和是否跨域有关
1、对于图片下载,需要设置响应头:`content-disposition`,该字段的作用是告诉浏览器,这是一个附件;对于excel表格,不管是否设置了响应头,都会下载。
2、window.open()没有跨域问题,没有浏览器兼容性问题
3、相对于a标签,window.open会好一些,a标签有浏览器的兼容性问题。
通过xhr转换的有多种
blob下载必须设置responseType:blob,否则返回的是一堆乱码的字符串。设置responseType:blob之后,浏览器将返回数据转成blob对象。
首先,创建xhr对象,请求接口
接下来是常见的浏览器网络请求接口4步骤:
createXHR(url, data, method, successCallBack, errCallBack) {
// 创建xhr对象
let xhr = new XMLHttpRequest();
// 连接
xhr.open(method, url);
// 发送
xhr.send(data);
// 必须设置responseType,否则返回的是字符串
xhr.responseType = "blob";
xhr.onreadystatechange = function() {
// xhr的请求状态有0,1,2,3,4
if(xhr.readyState === 4) {
// 返回的状态码
if(xhr.status === 200) {
// Content-Disposition获取文件名
successCallBack(xhr.response, xhr.getResponseHeader("Content-Disposition"));
} else {
errCallBack(xhr.response);
}
}
}
}
调用createXHR
var url = ‘http://127.0.0.1:3000/img‘;
createXHR(url, {},‘GET‘, function(res, header) {
let downloadName = header.split(‘filename="‘)[1].slice(0, -1);
blob([res], ‘image/jpeg‘, downloadName)
}, function(e) {
console.log(e);
})
blob方法
blob(data, content_type, downloadName) {
let blob = new Blob(data, { type: content_type});
// URL.createObjectURL生成一个DOMString, 包含了一个url对象,这个url对象与file对象或者blob对象有一个映射关系。 URL 的生命周期和创建它的窗口中的 document 绑定
let url = URL.createObjectURL(blob);
alabel(url, downloadName);
// 销毁url, 回收内存
URL.revokeObjectURL(url);
}
可以使用blob构造函数,那也可以使用h5的fileReader, 因为fileReader继承blob。fileReader的写法如下:
// FileReader转换对象不需要数组形式,blob是数组格式
fileReader(res, ‘1.jpg‘);
fileReader(data, downloadName) {
let reader = new FileReader();
reader.readAsDataURL(data);
reader.addEventListener(‘load‘, function() {
alabel(this.result, downloadName);
})
}
实验结果:
blob下载,使用的是Blob构造函数。最后还是要创建a标签下载。我们也知道a标签下载的一些缺点,同样blob下载也存在这样的缺点。
getResponseHeader,如果是跨域,只能获取到Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma几个响应头,如果需要获取其他的响应头,需要设置Access-Control-Expose-Headers
a标签下载有浏览器兼容问题。要兼容ie就要找其他的方法。前面有提到的window.open,还有一种是iframe
iframe标签
var url = ‘http://127.0.0.1:3000/img‘;
var iframe = document.createElement("iframe");
iframe.src = url;
iframe.style.display = "none";
document.body.appendChild(iframe);
iframe.click();
实验结果:
兼容性:ie,chrome
但是要设置content-disposition
东莞vi设计https://www.houdianzi.com/dgvi/ 豌豆资源网站大全https://55wd.com
还有一种ie自有的下载文件,ie10以上
window.navigator.msSaveBlob(blob, ‘1.jpg‘);
这种情况只能说是作死,但是没办法,实际情况也有可能有这么样。这种情况呢,只能是使用服务端做代理。这里使用的是node做代理。
页面:
// url是目标图片地址, serverApi是本地服务器接口
var url = ‘http://http://127.0.0.1:3001/img‘;
var serverApi = ‘http://127.0.0.1:3000/download‘
createXHR(serverApi, {url},‘POST‘, function(res, header) {
blob(res, ‘image/jpeg‘,‘1.jpg‘);
}, function(e) {/* */
console.log(e);
})
服务端:
app.post(‘/download‘, (req, res) => {
res.setHeader(‘Content-Type‘, ‘image/png‘)
request.get(req.body.url).pipe(res)
})
1、如果响应头设置有content-disposition,可以使用window.open
2、不满足1时,可以使用a标签下载
3、如果要兼容ie,可以使用navigator.msSaveBlob
4、如果没设置响应头,又跨域,那只能使用服务器代理
原文:https://www.cnblogs.com/Qooo/p/13847811.html