# 下载文件
- 简单的给地址url的get请求
<a href="后端文件下载接口地址" >下载文件</a>
- fetch请求 使用 Fetch API 获取到后端返回的字节流一般都会通过 “res.blob()” 转换成 blob 对象再进一步处理(Fetch API),那么问题来了 --- ”res.blob()” 又做了什么?
每次调用 res.blob() 方法都会执行 “consume body” 动作,“consume body” 的流程大概是这样的:
- 获取字节流的读取器
- 通过读取器读取所有的数据
- 把数据包装成 blob 对象并返回
自己处理字节流
fetch('example.zip')
.then((res) => {
// 获取读取器
const reader = res.body.getReader()
const type = res.headers.get('Content-Type')
const data = []
return new Promise((resolve) => {
// 读取所有数据
function push() {
reader.read().then(({done, value}) => {
data.push(value)
if (done) {
// 包装成 blob 对象并返回
resolve(new Blob(data, { type }))
} else {
push()
}
})
}
push()
})
})
.then(blob => {
const url = URL.createObjectURL(blob)
let a = document.createElement('a')
a.download = 'example.zip'
a.href = url
document.body.appendChild(a)
a.click()
a.remove()
})
function request () {
const req = new XMLHttpRequest();
req.open('POST', '<接口地址>', true);
req.responseType = 'blob';
req.setRequestHeader('Content-Type', 'application/json');
req.onload = function() {
const data = req.response;
const a = document.createElement('a');
const blob = new Blob([data]);
const blobUrl = window.URL.createObjectURL(blob);
download(blobUrl) ;
};
req.send('<请求参数:json字符串>');
};
function download(blobUrl) {
const a = document.createElement('a');
a.style.display = 'none';
a.download = '<文件名>';
a.href = blobUrl;
a.click();
document.body.removeChild(a);
}
request();
fetch(getRootPath_web() + `YjMessageIssue/download.shtml?taskid=${ids}` , {
method: 'POST',
})
.then(res => res.blob())
.then(data => {
let blobUrl = window.URL.createObjectURL(data);
const a = document.createElement('a');
a.style.display = 'none';
// a.download = '<文件名>';
a.href = blobUrl;
a.setAttribute('download', '报表.docx')
document.body.appendChild(a)
a.click();
document.body.removeChild(a);
});
- 下载zip
fetch('example.zip')
.then(res => res.blob())
.then(blob => {
// 通过 blob 对象获取对应的 url
const url = URL.createObjectURL(blob)
let a = document.createElement('a')
a.download = 'example.zip'
a.href = url
document.body.appendChild(a)
a.click()
a.remove() // document.body.removeChild(a)
})
.catch(err => {
console.error(err)
})
测试后可能会最新下载的文件回事缓存格式的(??),下新文件或者刷电脑对应的文件夹就好了
- 原生xmlhttprequest
function request () {
const req = new XMLHttpRequest();
req.open('POST', '<接口地址>', true);
req.responseType = 'blob';
req.setRequestHeader('Content-Type', 'application/json');
req.onload = function() {
const data = req.response;
const a = document.createElement('a');
const blob = new Blob([data]);
const blobUrl = window.URL.createObjectURL(blob);
download(blobUrl) ;
};
req.send('<请求参数:json字符串>');
};
function download(blobUrl) {
const a = document.createElement('a');
a.style.display = 'none';
a.download = '<文件名>';
a.href = blobUrl;
a.click();
document.body.removeChild(a);
}
request();
实际测试有问题,报错,等待查验
# 利用插件下载文件 js-file-download
cnpm install js-file-download
import axios form 'axios'
import qs from 'qs'
// 参数
const body = {
fileId: this.fileId
}
try {
axios.get('url', { params: body, responseType: 'arraybuffer' }).then(res => {
JsFileDownload(res.data, `测试文件_${new Date().toLocaleString()}.xls`)
})
} catch (e) { throw new Error(e) }
axios({
url: '/api/system/file/download/by/fileId',
method: 'post',
data: qs.stringify(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
},
responseType: 'arraybuffer'
}).then(res => {
JsFileDownload(res.data, `解析错误文件详情_${new Date().toLocaleString()}.xls`)
})
import fileDownload from 'js-file-download';
import Axios from 'axios'
import store from '@/store'
download() {
var requestUrl = "tcmp/api/devices/model";
var Authorization = store.state.user.token;
Axios({
method: 'get',
url: requestUrl,
headers: {
'Authorization': Authorization
},
responseType: 'blob'
}).then(res => {
fileDownload(res.data, 'deviceModel.xlsx');
});
}
responseType: 'arraybuffer'缺了会乱码,当然,也可以是其他的类型如blob
export function exportAlertInfo(data) {
return request({
url: '/openIot/backend/access/exportAlertInfo',
method: 'post',
data,
responseType: 'arraybuffer',
headers: {
Accept: 'application/json'
}
})
}
# 在欣方手写的垃圾代码,responseType为blob
$("#changemes").on('click',function(e){
var canshu= e.target.innerHTML;
var mes=JSON.stringify({file:canshu})
var url = "https://op.cintelcloud.com:6688/FileImgDownload/";
var xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader(
"x-header-token",
localStorage.getItem("Token")
);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.responseType = "blob";
xhr.send(mes);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var blob = this.response;
if(blob.size>0){
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a标签href
reader.onload = function (e) {
// 转换完成,创建一个a标签用于下载
var a = document.createElement('a');
a.download = canshu;
a.href = e.target.result;
$("body").append(a); // 修复firefox中无法触发click
a.click();
$(a).remove();
// window.location.reload();
}
}
}
};
} )
downexecl() {
exportAlertInfo(this.alarmForm).then(res => {
//res是ArrayBuffer
//方法一
//const blob = new Blob([res]);
//console.log(blob)
//const url = URL.createObjectURL(blob)
// let a = document.createElement('a')
// a.download = 'example.xls'
// a.href = url
// document.body.appendChild(a)
//a.click()
//document.body.removeChild(a)
//方法二
fileDownload(res, '告警数据信息.xls')
setTimeout(() => {
loading.close()
}, 1000)
}).catch(() => {
loading.close()
})
},
一种转url方法,借助
blob转url,使用插件fileDownload
# 下载闪烁问题
使用a标签或者window.open可能会存在闪烁问题
const iframe = document.createElement('iframe')
iframe.src = tem
iframe.style.display = 'none'
document.body.appendChild(iframe)
setTimeout(() => {
document.body.removeChild(iframe)
}, 1000)
# 下载流文件异常情况的处理
downloadBlob(url) {
downloadByUrl(url).then((res) => {
let { data } = res
if (data.type === 'application/json') {
let reader = new FileReader()
reader.addEventListener('loadend', () => {
const { message } = JSON.parse(reader.result)
this.$message.error(message || '下载失败')
})
reader.readAsText(data, 'utf-8')
} else {
let blob = new Blob([data])
let elink = document.createElement('a')
elink.download = data.attachSaveName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
}
})
}