需求
通过A链接的方式,把从后台获取到的文件下载到本地,实现在移动端,PC端都能下载
问题
通过ajax请求后端生成的文件流之后,创建BLOB文件进行下载,在PC端和移动安卓端都可以实现下载到本地和对应的手机,而在IOS端的话,是直接预览对应的blob文件地址 而不是下载对应的文件流,解决在IOS上也能实现下载(仅限Safari浏览器)
步骤
1.通过request,responseType的值为 'arraybuffer',请求对应的文件流
uni.request({
...handleRes,
responseType: 'arraybuffer',
success(res) {
// console.log(res, '返回数据');
// 这是返回的文件流
const file = res.data;
},
fail() {
uni.hideLoading();
}
})
2.通过将文件流转成blob对象
let blob = null;
if (headerDis.indexOf(tyepList.toString()) != -1) {
blob = new Blob([file], {
type: 'application/octet-stream;charset=UTF-8',
})
} else {
blob = new Blob([file], {
type: headerInfo['content-type'] ||
'application/octet-stream;charset=UTF-8',
})
}
3.通过创建A链接,通过download属性进行下载
async linkTodownloadFile(blob, fName) {
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, fName);
return false;
}
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.style.display = 'none'
link.href = url;
link.setAttribute('download', fName)
document.body.appendChild(link)
if (document.all) {
link.click();
} else {
// 兼容 Firfox
const evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, true);
link.dispatchEvent(evt);
}
document.body.removeChild(link) // 下载完成移除元素
window.URL.revokeObjectURL(url);
uni.hideLoading();
common.toast(107)
}
注意:这里需要主要的在IOS端如果自定义blob的type的话 download属性就只加文件名 而不需要后缀,会形成双重后缀.而且如果类型为steam的话就会是预览 而设置成steam的话就会直接下载文件,也就是第二步做的判断原因
4.完整的代码
uni.request({
url : 'xxx',
responseType: 'arraybuffer',
success(res) {
// console.log(res, '返回数据');
const file = res.data;
const headerInfo = res.header;
/** 获取文件名称 */
let fName = '';
/** 判断是否为可自定义类型还是默认 */
const tyepList = ['pdf'];
const headerDis = headerInfo['content-disposition'];
if (headerDis) {
const requestFileInfo = headerDis.split(';')[1];
if (store.state.app.SYSTEM_INFO.platform == 'ios') {
if (headerDis.indexOf(tyepList.toString()) != -1) {
fName = requestFileInfo;
} else {
fName = requestFileInfo.split('.')[0];
}
} else {
fName = requestFileInfo;
}
} else {
/** 判断文件是否有类型,没有就拿效应头 */
const fType = file.type || headerInfo['content-type'].split(';')[0];
for (const key in fileTypeConfig) {
if (fileTypeConfig[key].indexOf(fType) != -1) {
if (store.state.app.SYSTEM_INFO.platform == 'ios') {
fName = `${fileName}`;
} else {
fName = `${fileName}.${key}`;
}
break
}
}
}
/** 开始下载 */
let blob = null;
if (headerDis.indexOf(tyepList.toString()) != -1) {
blob = new Blob([file], {
type: 'application/octet-stream;charset=UTF-8',
})
} else {
blob = new Blob([file], {
type: headerInfo['content-type'] ||
'application/octet-stream;charset=UTF-8',
})
}
/** 判断是否为JSON 做逻辑处理 */
if (fName.indexOf('json') != -1) {
//通过FileReader读取数据
const reader = new FileReader();
// reader.readAsBinaryString(blob);
reader.readAsText(blob, 'utf8');
reader.onload = function() {
var content = JSON.parse(this.result); //这个就是解析出来的数据
if (content.code == 200) {
// common.toast(fName);
that.linkTodownloadFile(blob, fName);
resolve();
} else {
isLoading && uni.hideLoading();
common.toast(content.msg || 400);
}
}
} else {
// common.toast(fName);
that.linkTodownloadFile(blob, fName);
resolve();
}
},
fail() {
uni.hideLoading();
common.toast(108)
reject();
}
})
5.附件 fileTypeConfig的内容
export default {
xls: 'application/vnd.ms-excel',
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
csv: 'text/csv',
doc: 'application/msword',
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
pdf: 'application/pdf',
ppt: 'application/vnd.ms-powerpoint',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
png: 'image/png',
gif: 'image/gif',
jpeg: 'image/jpeg',
jpg: 'image/jpeg',
mp3: 'audio/mpeg',
aac: 'audio/aac',
html: 'text/html',
css: 'text/css',
js: 'text/javascript',
json: 'application/json',
abw: 'application/x-abiword',
arc: 'application/x-freearc',
avi: 'video/x-msvideo',
azw: 'application/vnd.amazon.ebook',
bin: 'application/octet-stream',
bmp: 'image/bmp',
bz: 'application/x-bzip',
bz2: 'application/x-bzip2',
csh: 'application/x-csh',
eot: 'application/vnd.ms-fontobject',
epub: 'application/epub+zip',
htm: 'text/html',
ico: 'image/vnd.microsoft.icon',
ics: 'text/calendar',
jar: 'application/java-archive',
jsonld: 'application/ld+json',
mid: 'audio/midi audio/x-midi',
midi: 'audio/midi audio/x-midi',
mjs: 'text/javascript',
mpeg: 'video/mpeg',
mpkg: 'application/vnd.apple.installer+xml',
odp: 'application/vnd.oasis.opendocument.presentation',
ods: 'application/vnd.oasis.opendocument.spreadsheet',
odt: 'application/vnd.oasis.opendocument.text',
oga: 'audio/ogg',
ogv: 'video/ogg',
ogx: 'application/ogg',
otf: 'font/otf',
rar: 'application/x-rar-compressed',
rtf: 'application/rtf',
sh: 'application/x-sh',
svg: 'image/svg+xml',
swf: 'application/x-shockwave-flash',
tar: 'application/x-tar',
tif: 'image/tiff',
tiff: 'image/tiff',
ttf: 'font/ttf',
txt: 'text/plain',
vsd: 'application/vnd.visio',
wav: 'audio/wav',
weba: 'audio/webm',
webm: 'video/webm',
webp: 'image/webp',
woff: 'font/woff',
woff2: 'font/woff2',
xhtml: 'application/xhtml+xml',
xml: 'text/xml',
xul: 'application/vnd.mozilla.xul+xml',
zip: 'application/zip,application/x-zip-compressed',
}