前端如何实现文件的在线预览?

2,673 阅读4分钟

起步

在计算机的世界中,有各种各样的文件,文件类型千奇百怪,作为一名前端开发工程师,我们如何来实现这些文件的在线预览呢?在上篇文章,我们已经实现了前端如何实现压缩包解析?,但是也仅仅是能够查看压缩包中的内容,并不能真实的去进行线上预览,这节就是在上节的基础上,举例一些我们日常经常接触的文件来进行预览:

  1. 文本类文件(虽然类型很多,但是处理方式基本都是一样的)

     const txtType = ['txt','html','htm','asp','jsp','js','xml','json','properties','md','gitignore','log','java','py','c','cpp','sql','sh','bat','m','bas','prg','cmd','vue','ts','tsx','yml','yaml','css',];
    
  2. 图片const pictureType = ['jpg', 'png', 'gif','webp'];

  3. 音视频文件(这里以.mp4举例)

  4. office文件

    const wordType = ['docx', 'doc']; // word
    const excelType = ['xls', 'xlsx']; // excel
    const pptType = ['ppt', 'pptx']; //ppt
    

回顾一下,上节我们已经完成的页面,可以看作左右两部分,左侧为我们解析出来的压缩包内文件的树结构,右侧为我们需要预览的文件。

1.jpg

我们监听了树的点击事件当点击某个文件的时候能够拿到这个文件的相关信息,包括File对象。

我们的dom结构大概是这样的,根据我们当前点击的文件类型展示不同的元素。

<div class='left'>
  <!-- 文件树结构 -->
  <a-tree></a-tree>
</div>
<div class='right'>
  <!-- 图片 -->
  <div v-if="pictureType.some(item => item == currentFile?.fileType)">
    <img :src="currentFile?.url" class="img" title="点击查看" v-viewer />
  </div>
  <!-- 文本 -->
  <div v-else-if="txtType.some((item) => item == currentFile?.fileType)" class="txt">
    <code>{{ textContent }}</code>
  </div>
  <!-- 视频 -->
  <div v-else-if="currentFile?.fileType == 'mp4'" style="width: 100%;">
    <video :src="currentFile.url"></video>
  </div>
  .....
</div>

那么我们如何读取文件的内容呢?这里我们需要用到一个api,FileReader - Web API | MDN

FileReader 接口允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 FileBlob 对象指定要读取的文件或数据。

调用这个构造函数会返回一个实例,通过这个实例我们就能将文件读取成任何我们想要的类型了。

1.文本类文件

// 文本内容
const textContent: string = ref('')
const reader: any = new FileReader()

// 文本文件,直接使用readAsText将文件读取为文本再展示即可
if (txtType.some((item) => item == fileType)) {
  reader.readAsText(file)
  reader.onload = () => textContent.value = reader.result
}

2.jpg

2. 图片类文件

将文件读取为base64的字符串,直接借助浏览器的img标签展示即可展示。

const reader: any = new FileReader()
// 图片
if (pictureType.some(item => item == fileType)) {
  reader.readAsDataURL(file)
  reader.onload = () => currentFile.value.url = reader.result
}

3.jpg

3. 音视频类文件

音视频文件的预览直接使用对应的标签即可,即和,但是都是通过src属性指定需要播放的内容的,所以,我们可以读取文件后调用URL.createObjectURL将对象转换为一个包含对象 URL 的字符串,然后赋值即可。

const reader: any = new FileReader()
// 视频
if (fileType == 'mp4') {
  reader.readAsArrayBuffer(file)
  reader.onload = () => currentFile.value.url = URL.createObjectURL(new Blob([reader.result], { type: 'video/mp4' }))
}

4.jpg

4. office文件

4.1 docx、xlsx、pdf

docx、xlsx、pdf文件的预览,我们需要借助vue-office这个库帮我们完成,这里贴上需要安装的依赖,使用方法很简单可以参考官方给出的示例vue-office简介 | vue-office

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

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

#pdf文档预览组件
npm install @vue-office/pdf vue-demi
4.1.1 word预览
<div v-else-if="wordType.some((item) => item == currentFile?.fileType)" class="word">
  <vue-office-docx :src="currentFile?.url" style=" height: 100vh;" />
</div>
//引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'

if (wordType.some((item) => item == fileType)) {
  reader.readAsArrayBuffer(file)
  reader.onload = () => currentFile.value.url = URL.createObjectURL(new Blob([reader.result]))  
}

5.jpg

4.1.2 excel预览
<div v-else-if="excelType.some((item) => item == currentFile?.fileType)" class="excel">
  <VueOfficeExcel :src="currentFile?.url" style="width: 100vw; height: 100vh;" />
</div>
//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'

if (excelType.some((item) => item == fileType)) {
  reader.readAsArrayBuffer(file)
  reader.onload = () => currentFile.value.url = URL.createObjectURL(new Blob([reader.result]))  
}

6.jpg

4.1.3 pdf预览
<div v-else-if="currentFile?.fileType == 'pdf'" class="pdf">
  <vueOfficePdf :src="currentFile?.url" style="width: 100%; height: 100vh;" />
</div>
//引入VueOfficePdf组件
import VueOfficePdf from '@vue-office/pdf'

if (fileType === 'pdf') {
  reader.readAsArrayBuffer(file)
  reader.onload = () => currentFile.value.url = URL.createObjectURL(new Blob([reader.result]))  
}

7.jpg

说明:vue-office这个插件库基本可以满足我们的预览需求,但是要注意@vue-office/docx对word的预览只支持docx后缀的文件,还不支持doc后缀的文件,如果有预览doc文件的需求可以选择一些文档预览服务,或者使用类似onlyoffice这种开源的库。

4.2 ppt文件预览

使用插件的方式目前找到了一款,PPTXjs这款库,进入链接后要先把源码下载下来,然后根据官方示例,将所需的文件引入完成预览。

8.jpg

使用onlyoffice

部署ONLYOFFICE,前端使用ONLYOFFICE相关的API完成office文档的预览,可以转到这篇文章onlyoffice实现office文件预览,下面贴上两张预览效果图:


11.jpg

13.jpg