公司系统出于安全性考虑,不允许控制台出现文件地址,避免有人把地址复制给没有该文件查看权限的人。所以只能后端返回文件流。
实现下载很简单,以下代码适合任何类型的文件下载:
const downloadFile = (file) => {
axios({
method: requestMethod,
url: requestUrl,
headers: {
Accept: 'text/plain, application/json',
...
},
responseType: "arraybuffer"
}).then(res => {
console.log(res)
const { data } = res;
if (res.headers["content-type"].startsWith("application/json")) {
let enc = new TextDecoder("utf-8");
let res = JSON.parse(enc.decode(new Uint8Array(data))); //转化成json对象
console.log(res)
message.error(res.resp_msg)
throw new Error(res.resp_msg);
}
const blob = new Blob([data]);
const url = window.URL.createObjectURL(blob); // URL.createObjectURL(object)表示生成一个File对象或Blob对象
let dom = document.createElement("a"); // 设置一个隐藏的a标签,href为输出流,设置download
dom.style.display = "none";
dom.href = url;
let fileName = file.fileName;
dom.setAttribute("download",fileName); // 指示浏览器下载url,而不是导航到它;因此将提示用户将其保存为本地文件
document.body.appendChild(dom);
dom.click();
}).catch(e => {
console.log(e)
})
//下面这种也行,但是如果接口报错没有提示,感觉用户体验不好
/*
let xhr = new XMLHttpRequest()
xhr.responseType = 'blob'
xhr.onload = function() {
const url = window.URL.createObjectURL(xhr.response);
const a = document.createElement('a');
a.href = url;
a.download = file.fileName;
a.click();
}
xhr.open(requestMethod, requestUrl)
xhr.send()*/
};
然后是预览,文件有word类型和图片。我们的word是由后端把文件转为pdf类型,饭后返回pdf文件流。
const previewClick = async (records) => {
if(records.fileName.indexOf('.zip')>0 ||
records.fileName.indexOf('.rar')>0){
message.info('压缩包文件不可预览')
return
}
const fileId = records.fileId;
if(records.fileType.indexOf('image/')>=0||records.fileType.indexOf('pdf')>=0){
// window.open(fileUrl); // 之前后端返回文件地址的做法
getFileStream(fileUrl, records.fileType.indexOf('image/')>=0?records.fileType:null)
}else{
const hide = message.loading('正在请求 PDF 地址');
const res = await services.getPdfStream(fileId)
if (res.resp_code === 200) {
hide();
// console.log(res.datas)
getFileStream(res.datas, null)
} else {
message.warning('无可用的文件预览地址');
hide();
}
}
};
const getFileStream = (id, type) => {
let requestUrl = requestUrl
let xhr = new XMLHttpRequest()
xhr.responseType = 'blob'
xhr.onload = function() {
let blob = xhr.response
// console.log(blob, 'blob')
let data
if(type){
data = new Blob([blob], { type: type }); // 根据实际的图片类型进行设置,常见的类型有 image/png,image.jpeg
}else{
data = new Blob([blob], {
type: 'application/pdf;charset=UTF-8'
})
}
let url = URL.createObjectURL(data);
// console.log(url)
window.open(url)
}
xhr.open(requestMethod, requestUrl)
xhr.send()
}
上面这个方法只适用于预览图片和后端可以转为pdf的word文档,excel和其他office文件没法实现。