vue预览和下载 pdf、ppt、word、excel文档,文件类型为链接或者base64格式或者文件流,

**

方法1:word、xls、ppt、pdf 这些文件, 如果预览的文件是链接可以直接打开,可用微软官方的预览地址

**

html 复制代码
 <iframe width="100%" :src="textVisibleURl " id="myFramePPT" style="border: none;background: #f3f5f8"
          title="预览" height="100%"></iframe>
javascript 复制代码
data(){
	return {
		textVisibleURl :''
	}
}

//可用window.open新开页面 或者 iframe 嵌入
//src是你文件的链接,需要可以公网访问,内网不可用,如http://********.docx
 this.textVisibleURl = `https://view.officeapps.live.com/op/embed.aspx?src=${src}`; //去掉头部一些不必要的按钮操作
window.open(this.textVisibleURl)

方法2:word、xls、ppt、pdf 这些文件, 如果预览的文件是类型是文件流或者base64格式

本次我的项目中后端返回的是base64格式,在预览中需要将base64格式转为文件流

javascript 复制代码
methods:{
getCustomerPoolList() {
      this.$api.getCustomerPoolList({ cityName: this.cityName.toString(), homeId: this.homeInterViewSelected.map(item => 			 item.homeId).toString() }).then(res => {
        res.data.forEach(item => {
          
          //此处两个遍历和预览无关,为业务逻辑,主要区分出文档和图片
          item.mapImageObj = item.fileList.filter(file => {
            return file.fileType == '.png' || file.fileType == '.jpg' || file.fileType == '.jpeg'
          })[0] || {}
          item.annexFileList = item.fileList.filter(file => {
            return file.fileType !== '.png' && file.fileType !== '.jpg' && file.fileType !== '.jpeg'
          }) || {}


			//item.annexFileList为所有文档的数组
          item.annexFileList.forEach((i, index) => {

          	//fileByte为base64格式,如上图,如果你的文件格式直接为文件流,此处 base64Str 到 byteArray 可跳过
            let base64Str = i.fileByte;
            const byteCharacters = atob(base64Str);
            const byteNumbers = new Array(byteCharacters.length);
            for (let i = 0; i < byteCharacters.length; i++) {
              byteNumbers[i] = byteCharacters.charCodeAt(i);
            }
            const byteArray = new Uint8Array(byteNumbers);

		
			//针对不同的文件添加不同的BlobType,此处转为文件流URL,文件为文件流可直接从此处开始
			//fileType 可以从fileName中截取,也可让后端返回
            if (i.fileType == '.pdf') {
              const blob = new Blob([byteArray], { type: 'application/pdf' });
              i.dialogImageUrl = URL.createObjectURL(blob);
             
            } else if (i.fileType == '.docx') {
            
              const blob = new Blob([byteArray], { type: 'application/msword' });
              i.dialogImageUrl = URL.createObjectURL(blob);

            } else if (i.fileType == '.ppt' || i.fileType == '.pptx') {
            
              const blob = new Blob([byteArray], { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' });

              i.dialogImageUrl = URL.createObjectURL(blob);
            } else {
            	//此处为excel文件,格式为".xlsx"
              const blob = new Blob([byteArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
              i.dialogImageUrl = URL.createObjectURL(blob);
              return
            }
          })
        })
        this.customerPoolObj = JSON.parse(JSON.stringify(res.data))

      })
    },
}

处理完后的数据,dialogImageUrl 为对象URL,预览全靠这个URL!!!

开始页面渲染

文件列表展示

预览所需的插件

powershell 复制代码
#docx文档预览组件方法1
npm install @vue-office/docx vue-demi

#docx文档预览组件方法2,本文没有使用此插件预览docx
npm install mammoth

#excel文档预览组件
npm install @vue-office/excel vue-demi

#pdf文档预览组件 ,本文中没有使用此插件预览PDF 
npm install @vue-office/pdf vue-demi

将两个文件复制到public目录下

ppt iframe的index.html代码,可适配移动端,pc端可删除适配移动端代码
下面的fileUrl:就是 上面处理完后的 dialogImageUrl

图片中的代码如下

typescript 复制代码
	
   let currentUrl = window.location.href;
    function getUrlParams(url) {
      const paramsRegex = /[?&]+([^=&]+)=([^&]*)/gi;
      const params = {};
      let match;
      while ((match = paramsRegex.exec(url))) {
        params[match[1]] = match[2];
      }
      return params;
    }
    let fileUrl = getUrlParams(currentUrl).fileUrl;
    console.log("fileUrl-->", fileUrl);
	//fileUrl:就是dialogImageUrl 
	// #pptx div的id
 $("#pptx").pptxToHtml({
      pptxFileUrl: fileUrl,
      pptxFileName: "fileName",
      slidesScale: "100%",
      slideMode: false,
      keyBoardShortCut: false,
 });
  // 适配移动端!!
    let timer = setInterval(() => {
      const $slides = $(".slides");
      if ($slides.children().length) {
        const slidesWidth = Math.max(
          ...Array.from($slides.children()).map((s) => s.offsetWidth)
        );
        const $wrapper = $("#pptx");
        const wrapperWidth = window.innerWidth;
        const wrapperHeight = window.innerHeight - 55;
        $wrapper.css({
          transform: `scale(${wrapperWidth / slidesWidth})`,
          "transform-origin": "top left",
          height: wrapperHeight * (1 / (wrapperWidth / slidesWidth)) + "px",
        });
        clearInterval(timer);
      }
    }, 100);

ppt/index.html中获取vue页面传进来的src链接获取到

html 复制代码
	  <div class="pdfBox1" v-show="fileObj.show">
      <div class="_head">
        <h5>{{ fileObj.fileName }}</h5>
        <i @click="closeLook" class="el-icon-arrow-left"></i>
      </div>
      <div class="word-wrap">
      	  <!-- 预览pdf -->
        <iframe :src="'./pdf/web/viewer.html?file=' + fileObj.url" height="100%" width="100%" id="iframe" title="预览"
          v-show="fileObj.type === '.pdf'" />
          
        <!-- 预览excel -->
        <vue-office-excel v-if="fileObj.type === '.xlsx'" :src="fileObj.url" @rendered="rendered"
          style="width: 100%; height: 100%" />

        <!-- 无适配图片,预览Docx  -->
        <VueOfficeDocx :src="fileObj.url" v-if="fileObj.type === '.docx'"></VueOfficeDocx>
        <!-- 预览ppt  -->
        <iframe width="100%" :src="pptSrc" id="myFramePPT" v-if="fileObj.type === '.pptx' || fileObj.type === '.ppt'"
          style="border: none;background: #f3f5f8" title="预览" height="100%"></iframe>
    
      </div>
    </div>

文件列表的点击事件调用toFileBlob

javascript 复制代码
<script>

	import VueOfficePdf from "@vue-office/pdf";
	import VueOfficeDocx from '@vue-office/docx'
	import VueOfficeExcel from "@vue-office/excel";
	import "@vue-office/docx/lib/index.css";
	import "@vue-office/excel/lib/index.css";
	export default {
	//val为文件列表的对象,主要参数为
	data(){
		return{
			fileObj: {
				dialogImageUrl:'',
				fileByte:'',
				fileName:'',
				fileType:'',
				url :'',
			},
			pptSrc :''
		}
	}
	
	 toFileBlob(val) {
	            console.log('aaa', val)
	       			
	     		this.fileObj.show = true;
	            this.fileObj.fileName = val.fileName;
	            this.fileObj.type = val.fileType
	            this.fileObj.fileByte = val.fileByte
	            this.fileObj.url = val.dialogImageUrl
	            
				if (val.fileType === '.ppt' || val.fileType === '.pptx') {
					//传入到iframe中
				    this.pptSrc = `/ppt/index.html?fileUrl=${val.dialogImageUrl}`;
				}else if (val.fileType === '.docx') {
	      
	       
	          		//预览word的第二种方法
	          		// let base64Str = val.fileByte;
	                // const byteCharacters = atob(base64Str);
	                // const byteNumbers = new Array(byteCharacters.length);
	                // for (let i = 0; i < byteCharacters.length; i++) {
	                //     byteNumbers[i] = byteCharacters.charCodeAt(i);
	                // }
	                /*  mammoth.convertToHtml({
	                     arrayBuffer: new Uint8Array(byteNumbers)
	                 }).then((resultObject) => {
	                     this.$nextTick(() => {
	                         this.wordText = resultObject.value;
	                     });
	                 }); */
					
					
	            }
	       }     
   </script> 

下载base64类型和文件流文件

javascript 复制代码
  downloadGO(data, reportName) {
      if (!data) {
        return
      }

      let base64Str = data;
      const byteCharacters = atob(base64Str);
      const byteNumbers = new Array(byteCharacters.length);
      for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
      }
      const byteArray = new Uint8Array(byteNumbers);

		//文件流省略上述步骤,直接下述开始,byteArray为文件流
      let url = window.URL.createObjectURL(new Blob([byteArray]))
      let link = document.createElement('a')
      link.style.display = 'none'
      link.href = url
      link.download = reportName //文件名
      document.body.appendChild(link)
      link.click()
    },
相关推荐
q***38511 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端
喵个咪1 小时前
go-kratos-admin 快速上手指南:从环境搭建到启动服务(Windows/macOS/Linux 通用)
vue.js·go
用户841794814561 小时前
vxe-gantt table 甘特图如何设置任务视图每一行的背景色
vue.js
小章鱼学前端2 小时前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
涔溪2 小时前
实现将 Vue3 项目作为子应用,通过无界(Wujie)微前端框架接入到 Vue2 主应用中(Vue2 为主应用,Vue3 为子应用)
vue.js·前端框架·wujie
源码技术栈4 小时前
什么是云门诊系统、云诊所系统?
java·vue.js·spring boot·源码·门诊·云门诊
lcc1874 小时前
Vue3 ref函数和reactive函数
前端·vue.js
艾小码5 小时前
还在为组件通信头疼?defineExpose让你彻底告别传值烦恼
前端·javascript·vue.js
带只拖鞋去流浪5 小时前
迎接2026,重新认识Vue CLI (v5.x)
前端·vue.js·webpack
Coder-coco5 小时前
游戏助手|游戏攻略|基于SprinBoot+vue的游戏攻略系统小程序(源码+数据库+文档)
java·vue.js·spring boot·游戏·小程序·论文·游戏助手