vue2.0纯前端预览附件方法汇总
一、使用iframe预览
1.使用 Office 在线查看器
支持 Word 和 Excel 和Pdf 文档预览,兼容性好。不需要额外安装库,直接使用在线服务。 文件地址必须公网
<iframe :src="textVisibleURl" frameborder="0" width="700" height="800"></iframe>// 打开文件预览clickPreview(pitem){if(/\.pdf$/i.test(pitem.name)){this.textVisibleURl = pitem.url;}elseif(/\.(doc|docx|xls|xlsx|ppt|pptx|pdf)$/i.test(pitem.name)){let src = pitem.url;//这个地址预览的时候有一些按钮// this.textVisibleURl = `https://view.officeapps.live.com/op/view.aspx?src=${src}`;this.textVisibleURl =`https://view.officeapps.live.com/op/embed.aspx?src=${src}`;}elseif(/\.csv$/i.test(pitem.name)){this.textVisibleURl =`http://view.xdocin.com/xdoc?_xdoc=${pitem.url}`;}},
2.XDOC文档预览服务
<iframe
class="iframeDom":src="textVisibleURl"
frameborder="0"
width="100%"
height="800"></iframe>clickPreview(){var xurl ='https://view.xdocin.com/view?src=';
xurl +=encodeURIComponent(newV);let ops ={pdf:true,// toolbar: false,// limit: '2,1', //只显示第二页// limit: '2', //显示一二页limit:'5,4',//显示一二页// limit: '2,3', //显示二三四页};for(var a in ops){
xurl +='&'+ a +'='+encodeURIComponent(ops[a]);}this.textVisibleURl = xurl;}
XDOC官网地址:https://view.xdocin.com/
二、vue-office
支持多种文件(.docx、.pdf、.excel)预览的vue组件套装,支持vue2/3。
只需提供文档的src(网络地址)即可完成文档预览
(其中word是转换成html 和css,可以对文档内容进行高亮定位什么的)
有文档网络地址,比如 https://***.docx
文件上传时预览,此时可以获取文件的ArrayBuffer或Blob
具体效果可以参考: https://501351981.github.io/vue-office/examples/dist/#/docx
//docx文档预览组件
npm install @vue-office/docx vue-demi
//excel文档预览组件
npm install @vue-office/excel vue-demi
//pdf文档预览组件
npm install @vue-office/pdf vue-demi
1.docx预览
// 使用网络地址<template><vue-office-docx :src="docx" @rendered="rendered"/></template><script>//1.引入VueOfficeDocx组件import VueOfficeDocx from'@vue-office/docx'//引入相关样式import'@vue-office/docx/lib/index.css'exportdefault{components:{
VueOfficeDocx
},data(){return{docx:'http://static.shanhuxueyuan.com/test6.docx'//设置文档网络地址,可以是相对地址}},methods:{rendered(){
console.log("渲染完成")}}}</script>//********************************************************************************************//2.element的上传组件,获取文件的arrayBuffer<template><div id="docx-demo"><el-upload :limit="1":file-list="fileList" accept=".docx":beforeUpload="beforeUpload" action=""><el-button size="small" type="warning">点击上传</el-button></el-upload><vue-office-docx :src="src"/></div></template><script>import VueOfficeDocx from'@vue-office/docx'import'@vue-office/docx/lib/index.css'exportdefault{components:{
VueOfficeDocx
},data(){return{src:'',fileList:[]}},methods:{beforeUpload(file){let reader =newFileReader();
reader.readAsArrayBuffer(file);
reader.onload=(loadEvent)=>{let arrayBuffer = loadEvent.target.result;this.src = arrayBuffer
};returnfalse}}}</script>//********************************************************************************************//3.原生的input type="file"<template><div><input type="file" @change="changeHandle"/><vue-office-docx :src="src"/></div></template><script>import VueOfficeDocx from'@vue-office/docx'import'@vue-office/docx/lib/index.css'exportdefault{components:{
VueOfficeDocx
},data(){return{src:''}},methods:{changeHandle(event){let file = event.target.files[0]let fileReader =newFileReader()
fileReader.readAsArrayBuffer(file)
fileReader.onload=()=>{this.src = fileReader.result
}}}}</script>
2.excel文档预览
<template><vue-office-excel :src="excel" @rendered="rendered"/></template><script>//引入VueOfficeExcel组件import VueOfficeExcel from'@vue-office/excel'//引入相关样式import'@vue-office/excel/lib/index.css'exportdefault{components:{
VueOfficeExcel
},data(){return{excel:'http://static.shanhuxueyuan.com/demo/excel.xlsx'//设置文档地址}},methods:{rendered(){
console.log("渲染完成")}}}</script>
3.pdf文档预览
<template><vue-office-pdf :src="pdf" @rendered="rendered"/></template><script>//引入VueOfficePdf组件import VueOfficePdf from'@vue-office/pdf'exportdefault{components:{
VueOfficePdf
},data(){return{pdf:'http://static.shanhuxueyuan.com/test.pdf'//设置文档地址}},methods:{rendered(){
console.log("渲染完成")}}}</script>
具体代码可以参考: https://gitee.com/ye-jizeng/vue-office#https://gitee.com/link?target=https%3A%2F%2F501351981.github.io%2Fvue-office%2Fexamples%2Fdist%2F
三、file-viewer插件(封装好的预览组件)
1.通过上传获取文件arrayBuffer
具体效果可以参考: https://zhuye1993.github.io/file-view/dist/index.html
代码地址: https://github.com/zhuye1993/file-view
参考文章链接: https://juejin.cn/post/7071598747519549454
// 主要代码<template><div :class="{ hidden }"><div class="banner"><div class="container"><h1><div>
在线文档查看
<input class="file-select" type="file" @change="handleChange"/></div></h1></div></div><div class="container"><div v-show="loading"class="well loading">正在加载中,请耐心等待...</div><div v-show="!loading"class="well" ref="output"></div></div></div></template><script>import{ getExtend, readBuffer, render }from"@/components/util";import{ parse }from"qs";/**
* 支持嵌入式显示,基于postMessage支持跨域
* 示例代码:
*
*/exportdefault{name:"HelloWorld",props:{msg: String,},data(){return{// 加载状态跟踪loading:false,// 上个渲染实例last:null,// 隐藏头部,当基于消息机制渲染,将隐藏hidden:false,};},created(){// 允许使用预留的消息机制发送二进制数据,必须在url后添加?name=xxx.xxx&from=xxxconst{ from, name }=parse(location.search.substr(1));if(from){
window.addEventListener("message",(event)=>{const{ origin,data: blob }= event;if(origin === from && blob instanceofBlob){// 构造响应,自动渲染const file =newFile([blob], name,{});this.hidden =true;this.handleChange({target:{files:[file]}});}});}},methods:{asynchandleChange(e){this.loading =true;try{const[file]= e.target.files;const arrayBuffer =awaitreadBuffer(file);this.loading =false;this.last =awaitthis.displayResult(arrayBuffer, file);}catch(e){
console.error(e);}finally{this.loading =false;}},displayResult(buffer, file){// 取得文件名const{ name }= file;// 取得扩展名const extend =getExtend(name);// 输出目的地const{ output }=this.$refs;// 生成新的domconst node = document.createElement("div");// 添加孩子,防止vue实例替换dom元素if(this.last){
output.removeChild(this.last.$el);this.last.$destroy();}const child = output.appendChild(node);// 调用渲染方法进行渲染returnnewPromise((resolve, reject)=>render(buffer, extend, child).then(resolve).catch(reject));},},};</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>.banner {overflow: auto;
text-align: center;/* background-color: #12b6ff; */color: #000;}.hidden .banner {display: none;}.hidden .well {height:calc(100vh - 12px);}.file-select {position: absolute;left:5%;top: 17px;
margin-left: 20px;}.banner div {color: #000;}.banner h1 {
font-size: 20px;
line-height:2;margin:0.5em 0;}.well {display: block;
background-color: #f2f2f2;border: 1px solid #ccc;margin: 5px;width:calc(100%- 12px);height:calc(100vh - 73px);overflow: auto;}.loading {
text-align: center;
padding-top: 50px;}.messages .warning {color: #cc6600;}</style><style>.pptx-wrapper {
max-width: 1000px;margin:0 auto;}</style>
2.通过上传获取文件arrayBuffer和Url方式(都转换成html 和css方式)
具体效果可以参考: https://viewer.flyfish.group/
代码地址:https://git.flyfish.dev/flyfish-group/file-viewer-demo
如果要获取最新的源码,要找人家开放私库权限(文章链接里面有)
参考文章链接: https://blog.csdn.net/wybaby168/article/details/122842866?spm=1001.2014.3001.5502
//对应解析的插件
word预览是用的docxjs
pdf预览是用的pdfjs
ppt预览是用的pptx2html
// 主要代码<template><div class="file-viewer"><div class="name">{{filename}}</div><div v-if="error"class="content loading">{{error}}</div><template v-else><div v-show="loading"class="content loading">{{message}}</div><div v-show="!loading"class="content" ref="output"></div></template></div></template><script>import{ getExtend, render }from"./util";import axios from"axios";import{ readBuffer }from"../../common/util";const messages ={loading:'正在加载中,请耐心等待...',reading:'正在努力解析文件...',errorLoading:e=>`加载文件异常:${e}`,errorReading:e=>`读取文件异常:${e}`,}exportdefault{name:"FileViewer",props:{file:{type:[File, Blob, ArrayBuffer],description:'通过文件对象或二进制数据加载文档'},url:{type: String,description:'通过url加载文档'}},data(){return{// 加载状态跟踪loading:false,// 存在错误时有值error:'',// 消息message:'',// 文件名filename:'',}},watch:{// url改变时,重新请求url(){this.loadFromUrl();},file(file){this.resolveFile(file);},},mounted(){if(this.file){this.resolveFile(this.file);}this.loadFromUrl();},methods:{// 从url加载asyncloadFromUrl(){// 要预览的文件地址const{ url }=this;if(!url)return;this.startLoading(messages.loading)const filename = url.substr(url.lastIndexOf('/')+1);// 拼接ajax请求文件内容try{const{ data }=awaitaxios({ url,method:'get',responseType:'blob'});// 展示错误if(!data)returnthis.showError('文件下载失败');// 手动构建一个fileconst file =this.wrap(data, filename);// 解析文件returnthis.resolveFile(file);}catch(e){this.showError(messages.errorLoading(e));}finally{this.endLoading();}},// 包装filewrap(data, filename){if(data instanceofFile){return data;}if(data instanceofBlob){returnnewFile([ data ], filename,{});}if(data instanceofArrayBuffer){returnthis.wrap(newBlob([ data ]));}},// 处理并解析文件asyncresolveFile(data){// 停止之前的加载if(this.loading)this.endLoading();// 安全的包装文件const file =this.wrap(data);// 开始加载this.startLoading(messages.reading);try{this.filename = file.name &&decodeURIComponent(file.name)||'';const arrayBuffer =awaitreadBuffer(file);this.last =awaitthis.displayResult(arrayBuffer, file)}catch(e){this.showError(messages.errorReading(e));}finally{this.endLoading();}},// 展示渲染最终效果displayResult(buffer, file){// 取得文件名const{ name }= file;// 取得扩展名const extend =getExtend(name);// 输出目的地const{ output }=this.$refs;// 生成新的domconst node = document.createElement('div');// 添加孩子,防止vue实例替换dom元素if(this.last){
output.removeChild(output.lastChild);this.last.$destroy();}const child = output.appendChild(node);// 调用渲染方法进行渲染returnnewPromise((resolve, reject)=>render(buffer, extend, child).then(resolve).catch(reject));},showError(message){this.error = message;},startLoading(message){this.loading =true;this.message = message;this.error ='';},endLoading(){this.loading =false;this.message ='';}}}</script><style scoped>.file-viewer {position: relative;}.content {display: block;
background-color: #f2f2f2;border: 1px solid #ccc;margin: 5px;width:calc(100%- 12px);height:calc(100vh - 73px);overflow: auto;}.loading {
text-align: center;
padding-top: 50px;}.name {position: absolute;bottom:0;left:0;width:100%;padding: 13px 0;
font-size: 20px;
text-shadow: 2px 2px #616161;
pointer-events: none;color: white;background:rgba(31,31,31,0.22);
text-align: center;
z-index:10000;}</style>
四、vue-pdf插件
arrayBuffer和Url方式都支持
npm install --save vue-pdf
import pdf from'vue-pdf'
1.全文预览
<template><div><pdf
v-for="i in numPages":key="i":page="i":src="pdfUrl"
style="width: 100%"
@num-pages="pageCount = $event"></pdf></div></template><script>import pdf from'vue-pdf';exportdefault{name:'PDF',components:{ pdf },data(){return{pageCount:10,//当前页pdfUrl:'',src:'https://.pdf',// pdf文件地址numPages:0,//总页数};},mounted(){this.loadPdfHandler();},methods:{asyncloadPdfHandler(){this.pdfUrl = pdf.createLoadingTask(this.src);this.pdfUrl.promise.then(pdf=>{this.numPages = pdf.numPages;});},},};</script>
2.指定页数,直接预览到某页的
<template><div class="pdf-preview-out" v-loading="boxLoading"><!-- 上部 外层容器 用于滚动--><div class="scroll-box"><!-- 用于截取调缩放后的空白区域 --><div class="pdf-box"><!--pdf预览区域(会被缩放)--><div :style="getPdfSize()"class="pdf-scale-box"><!-- 预览组件 --><pdf
:src="url":page="currentPage"
@num-pages="getTotalPage"
@page-loaded="pageLoaded"
@loaded="mountedLoaded"></pdf></div></div></div><!-- 底部操作栏 --><div class="bottom-tools"><div>共 {{ pageTotal }} 页</div><div class="page"><el-button round type="primary":disabled="currentPage === 1" @click="chengPage">
上一页
</el-button><!-- 页码展示及跳转 --><el-button
round
type="primary":disabled="currentPage === pageTotal"
@click="chengPage('+')">
下一页
</el-button></div><div class="scale"><el-button
type="primary"
icon="el-icon-minus"circle:disabled="pageScale - 0.1 < 0.3"
@click="scalePage"></el-button><el-button
type="primary"
icon="el-icon-plus"circle:disabled="pageScale + 0.1 > 1"
@click="scalePage('+')"></el-button></div></div></div></template><script>// 插件引入import pdf from'vue-pdf';exportdefault{components:{
pdf,},data(){return{// 总页数pageTotal:0,// 当前页currentPage:3,// 缩放比例pageScale:0.8,// 遮罩boxLoading:true,pageChangeTimer:null,url:'https://.pdf',};},methods:{// 获取到pdf总页数时触发 会传入总页数getTotalPage(page){this.pageTotal = page;},// 初始化加载完毕触发mountedLoaded(){// 去除遮罩this.boxLoading =false;},// 每加载完成一页时触发(初始化/翻页时均会触发)pageLoaded(){// 重新设置pdf预览区域容器外容器的尺寸this.setPdfBoxSize();},// 设置pdf预览区域容器的缩放尺寸getPdfSize(){return{transform:`scale(${this.pageScale})`,};},// 点击缩放时触发scalePage(type){// 改变缩放比例let sacle =0;if(type ==='+'){
sacle =this.pageScale +0.1;}else{
sacle =this.pageScale -0.1;}// 可能会涉及js的精度损失 保留一位小数即可this.pageScale =Number(sacle.toFixed(1));// 缩放后pdf预览区域容器中会有留白 重新设置pdf预览区域容器外容器的尺寸this.setPdfBoxSize();},// 方法 翻页chengPage(type){// 防抖 0.5秒内不再次触发时执行if(this.pageChangeTimer){clearTimeout(this.pageChangeTimer);}// 执行翻页this.pageChangeTimer =setTimeout(()=>{if(type ==='+'){this.currentPage +=1;}else{this.currentPage -=1;}// 翻页后将滚动条归位到顶部this.scrollbarReset();this.pageChangeTimer =null;},500);},// 方法 滚动条归位到顶部scrollbarReset(){let boxDom = document.querySelector('.scroll-box');
boxDom.scrollTop =0;},// 方法 设置pdf预览区域容器外容器的尺寸setPdfBoxSize(){// 缩放后 pdf的显示上会缩小 但元素的实际占地尺寸不会变化(仍是原尺寸) 导致可能会出现部分区域留白 通过改变pdf预览区域容器外容器的尺寸 来将留白区域hidden// 获取pdf的原尺寸let boxDom = document.querySelector('.pdf-scale-box');// 获取要设置尺寸的元素domlet setDom = document.querySelector('.pdf-box');// 如有缩放 高度根据缩放比例变化(48px是预留的上下外边距)if(this.pageScale !==1&& boxDom && setDom){
setDom.style.height =`${boxDom.clientHeight *this.pageScale +48}px`;}else{
setDom.style.height ='';}// console.log(this.pageScale)// console.log(boxDom.clientWidth * this.pageScale)},},};</script><style lang="scss" scoped>.pdf-preview-out {// 高度为占满父组件中的外层容器(若不需要在父组件中设置高度 也可以在本组件中直接设置为所需值)height:100%;// border: 1px solid #909;&,
div {-webkit-box-sizing: border-box;-moz-box-sizing: border-box;
box-sizing: border-box;}// 滚动容器.scroll-box {// 高度按比例 溢出滚动height: 800px;overflow: auto;border: 2px solid #c0d8f3;
border-bottom: none;
border-radius: 6px;
background-color: #eeeeee;// 滚动条样式&::-webkit-scrollbar {width: 10px;}&::-webkit-scrollbar-thumb {
background-color: #c0d8f3;
border-radius: 6px;}&::-webkit-scrollbar-track {
background-color: transparent;
border-radius: 6px;}// 用于缩放后截取掉不需要的空白的容器.pdf-box {overflow: hidden;padding: 24px;// border: 1px solid rgb(165, 11, 236);}// pdf预览区容器.pdf-scale-box {
box-shadow: 0px 0px 20px 5px #666565;// border: 2px solid #090;// 设置缩放的中心点
transform-origin: center top;transition:0.2s;}}.bottom-tools {height: 50px;
line-height: 50px;
background-color: #c0d8f3;border: 1px solid #5caaf8;
border-radius: 6px;display: flex;padding: 0px 24px;.page {color: #636a70;
flex-grow:1;// border: 1px solid #909;
span {
margin-right: 20px;}}.scale {// border: 1px solid #909;
text-align: right;}}}</style>
链接: https://blog.csdn.net/m0_71537867/article/details/131614868
五、pptx.js插件
另外预览ppt还有一个插件pptx但是我没试,放两个链接,你们可以自己试试
链接: https://www.cnblogs.com/xyulz/p/17812301.html
链接: https://blog.51cto.com/u_16213605/8386577
重要写完了~~~~~心累
版权归原作者 程序媛_MISS_zhang_0110 所有, 如有侵权,请联系我们删除。