公司最近有个功能需求,是让后端的文件流通过接口返回到前端,前端展示文件,所以记录一下爬坑过程
下载功能封装为download.js文件:
import Axios from "axios";
import {Message} from 'element-ui';
import {doEncrypt,doDecryptStr} from './sm2-1';
//下载文件
export default function download(url,params={},functype){
return new Promise((resolve)=>{
getData(url,params,functype).then(res=>{
const cont=res;
const data=params;
const fileTypeArr={
pdf:"application/pdf;charset=UTF-8", //pdf格式
doc:"application/msword;charset=UTF-8", //文档格式
zip:"application/zip;charset=UTF-8", //zip格式
}
let fileType=""
switch(data.fileType){
case '01':
fileType=fileTypeArr.pdf;
break;
case '05':
fileType=fileTypeArr.doc;
break;
}
const header=cont.headers["content-disposition"];
if(!header) return Message.error({
message:"下载失败",
duration:3000
});
const stringT=header.split("=")[1]
const fileName=decodeURI(stringT,"utf-8").replace('.pdf','')
const blob=new Blob([res.data],{
type:fileType?fileType:"application/pdf;charset=UTF-8"
});
//默认下载功能,没有functype这个参数
if(!functype){
if("download" in document.createElement("a")){
const link=document.createElement("a");
link.download=fileName;
link.style.display="none";
link.href=URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
resolve("success");
}else{
navigator.msSaveBlob(blob.fileName);
}
}else if(functype=='preview'){
//functype这个参数传preview则为预览功能
let herf=URL.createObjectURL(blob);
this.$store.commit("getPdfUrl",herf);
this.$router.push({
name:"preview",
query:{cache:true}
})
}
})
})
}
//文件下载返回blob数据
function getData(url,params={}){
return new Promise((resolve,reject)=>{
Axios({
url,
method:"post",
responseType:"blob",
headers:{
"data-token":sessionStorage.getItem('data-token'),
"Content-Type":"application/json;charset=UTF-8"
},
data:{
data:params.data?doEncrypt(params.data):doEncrypt(JSON.stringify(params))
}
}).then(res=>{
resolve(res);
}).catch(error=>{
let url=sessionStorage.getItem('url')
url=url&&url.replace(/\"/g,"")
if(error.response.status==401&&url){
window.location=`${url}`
}else{
Message.error({
message:`连接出错(${error.response.status})`,
duration:3000
})
}
reject('error')
})
})
}
在main.js项目入口文件中全局挂载
import download from './utils/download'
Vue.prototype.$download=download
在需要使用的文件中调用,调用方法如下:
this.$download('/xxxx/url',parmas)
this.$download('/xxxx/url',parmas,'preview')
文件预览页preview.vue
<template>
<div>
<div class="container" v-loading="loading" @scroll="scroll">
<pdf ref="pdf" v-for="item in numPages" :key="item" :src="url" :page="item" @loaded="loadPdfHandler"></pdf>
<el-button type="primary" class="btn" @click="downLoad">下载</el-button>
</div>
</div>
</template>
<script>
import pdf from "vue-pdf";
import CMapReaderFactory from "vue-pdf/src/CMapReaderFactory.js";
export default {
name:"preview",
components:{
},
data(){
return{
url:"",
totalPage:undefined,
numPages:undefined,
id:"",
loading:true
};
},
mounted(){
//获取所需参数
this.id=this.$store.state.id;
this.url=this.$store.state.pdfUrl;
this.getNumPages()
},
methods:{
//动态渲染
getNumPages(){
this.$nextTick(()=>{
let loadingTask=pdf.createLoadingTask(this.url,CMapReaderFactory);
loadingTask.promis.then(pdf=>{
this.numPages=5;//一次渲染五页
this.totalPage=pdf.numPages;
}).catch((err)=>{
console.error(err,'pdf加载失败')
})
})
},
scroll(){
//滚动渲染
const el=document.getElementByClassName('container')[0];
const offsetHeight=el.offsetHeight;
if(offsetHeight+scrollTop-scrollHeight>=-1){
if(this.numPages<this.totalPage){
this.numPages++
}
}
},
loadPdfHandler(){
this.loading=false
},
downLoad(){
let params=JSON.stringify({
id:this.id
fileType:"01"
});
const data={
data:params,
};
this.download('/xxxx/url',data);
};
}
}
</script>
如果有任何问题欢迎沟通交流!