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()
    },
相关推荐
只会写Bug1 小时前
后台管理项目中关于新增、编辑弹框使用的另一种展示形式
前端·vue.js
枫叶丹42 小时前
【HarmonyOS 6.0】ArkWeb PDF预览回调功能详解:让PDF加载状态可控可感
开发语言·华为·pdf·harmonyos
M ? A2 小时前
Vue v-bind 转 React:VuReact 怎么处理?
前端·javascript·vue.js·经验分享·react.js·面试·vureact
军军君012 小时前
数字孪生监控大屏实战模板:政务服务大数据
前端·javascript·vue.js·typescript·前端框架·echarts·less
优化控制仿真模型3 小时前
【26年6月最新】英语六级2015-2025年12月历年真题及答案PDF
经验分享·pdf
忆往wu前3 小时前
前端请求三部曲:Ajax / Fetch / Axios 演进与 Vue 工程化封装
前端·vue.js
.Cnn3 小时前
Ajax与Vue 生命周期核心笔记
前端·javascript·vue.js·笔记·ajax
吴声子夜歌4 小时前
Vue3——渲染函数
前端·vue.js·vue·es6
Ruihong4 小时前
你的 Vue KeepAlive 组件,VuReact 会编译成什么样的 React 代码?
vue.js·react.js·面试
Ruihong4 小时前
你的 Vue slot 插槽,VuReact 会编译成什么样的 React 代码?
vue.js·react.js·面试