利用blob和XMLHttpRequest实现web端跨域文件下载

之前在项目中遇到了需要实现文件下载的方法,在网络上查找资料后,发现了下面这种通过Blob和XMLHttpRequest实现文件下载的方法。

非跨域文件的下载

// 通过 ajax 获取 Blob
function getBlob(url) {
return new Promise(resolve => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
}
};
xhr.send();
});
}
// 保存重命名
function saveAs(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.click();
window.URL.revokeObjectURL(link.href);
}
}
// 封装保存方法
function download(url, filename) {
getBlob(url).then(blob => {
saveAs(blob, filename);
});
}

// 使用例子
download('https://github.com/vuejs/vue-router', 'vue-router.html');

上边这种方式可以解决非跨域文件的下载问题,但是遇到跨域文件时就无能为力了。

跨域文件的下载

后来,我又继续查了下资料,找到了下面这种方式,可以解决跨域文件的下载问题。

这里直接上代码:

/**
* URL方式保存文件到本地
* @param data 文件的blob数据
* @param name 文件名
*/
function saveAs(data, name) {
const urlObject = window.URL || window.webkitURL || window;
const export_blob = new Blob([data]);
const save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = urlObject.createObjectURL(export_blob);
save_link.download = name;
save_link.click();
}

/**
* 根据文件url获取文件名
* @param url 文件url
*/
function getFileName(url) {
const num = url.lastIndexOf('/') + 1;
let fileName = url.substring(num);
//把参数和文件名分割开
fileName = decodeURI(fileName.split('?')[0]);
return fileName;
}

/**
* 获取页面文件名
* @param url 文件url
*/
function downloadUrlFile(url) {
const newUrl = url.replace(/\\/g, '/');
const xhr = new XMLHttpRequest();
xhr.open('GET', newUrl, true);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
// 获取文件blob数据并保存
const fileName = getFileName(newUrl);
saveAs(xhr.response, fileName);
}
};

xhr.send();
}

export default downloadUrlFile;