各种类型文件的预览(图片、音视频、pdf、office、md、zip)

1,306 阅读3分钟

文件预览是我们经常遇到的业务场景,不同类型的文件有不同的处理方式。GitHub Demo地址: github.com/beat-the-bu…

浏览器支持的文件类型

这一类文件预览,都是去使用我们熟悉的HTML标签。

图片

使用<img>标签:

<img src="img.png" />

音频

使用<audio>标签:

<audio controls> 
    <source src="audio.mp3" type="audio/mpeg"> 
    您的浏览器不支持 audio 元素。 
</audio>

视频

使用<video>标签:

<video controls loop>
    <source src="movie.mp4" type="video/mp4">
    您的浏览器不支持 video 标签。
</video>

PDF

使用<embed>标签,<embed> 标签定义外部资源的容器,例如网页、图片、媒体播放器或插件应用程序。

<embed src="PDF.pdf">

也可以使用第三方插件vue-pdf-embed

以上浏览器可以识别的文件类型,均可以用window.open的方式打开一个窗口直接预览,但是要注意PDF类型的文件,需要看一下浏览器关于PDF的设置是预览模式还是下载模式:

截屏2024-07-07 21.37.12.png

office系列的文件

我们知道,office系列的文件只有office软件才能打开,浏览器是不认识这一类文件的。要想预览office文件,我们一般有两种方式:

方法一:使用office官方自带的在线预览功能。在下面的链接后面拼接上office文件的地址:view.officeapps.live.com/op/view.asp…

方法二:后端处理,将office文件转成PDF文件,在这里不做详细讨论。

markdown文件

这一类文件本质上是文本,该文本可以转换成HTML。我们需要两个插件,一个是marked,用于将markdown的语法转成HTML,另一个是highlight.js,用于给markdown中的代码块加一些高亮的展示。

import { onMounted, nextTick, ref } from 'vue'
import { marked } from 'marked'
import hljs from 'highlight.js'
import 'highlight.js/styles/github.css';

let str = '# Marked in the browser\n\nRendered by **marked**.\n ```js\nvar a = 1;\n```'
const html = ref('')

onMounted(async () => {
  let trans = marked.parse(str);
  html.value = trans
  await nextTick()
  hljs.highlightAll();
})

效果如下:

截屏2024-07-07 22.22.04.png

zip文件

对于压缩文件,我们需要将文件解析出来,得到一个子文件的列表,然后将子文件列表展示出来。我们需要借助jszip

我们需要一个文件输入框、读取文件按钮、按钮点击之后展示压缩包的内容。

<input type="file" id="fileId" />
<Button @click="readZip">读取压缩文件</Button>

<Table :dataSource="dataList" :columns="columns" :pagination="false" :rowKey="(record, index) => index">
  <template #fileContent="{ record, text }">
    <div v-if="text.indexOf('http') < 0">{{ text }}</div>
    <Button type="link" v-else @click="downloadByUrl({
      url: text,
      fileName: record.fileName.split('/')[1]
    })">下载</Button>
  </template>
</Table>

准备一个zip文件,里面有md、pdf、jpeg文件:

截屏2024-07-13 22.20.01.png

后面就是对jszip的使用。

关键方法一:jszip.loadAsync,传入File类型,返回一个带压缩包内容的Promise:

 jszip.loadAsync(currFile).then(res => {
      console.log(res) // 目录以及里面的内容
 })

关键方法二:file方法和async方法

file方法可以根据压缩包内的文件名读取文件,async可以传读取的方式:

res.file(fileItem.name)?.async('blob').then(data => {
  dataList.value.push({
    fileName: fileItem.name,
    fileType: '图片',
    fileContent: URL.createObjectURL(data),
  })
})

完整代码如下:

function readZip() {
  var file = document.getElementById('fileId')
  if (file && file.files && file.files[0]) {
    dataList.value = []
    let currFile = file.files[0]
    let jszip = new JSZip()

    jszip.loadAsync(currFile).then(res => {
      for (let key in res.files) {
        let fileItem = res.files[key]
        if (!fileItem.dir && fileItem.name.indexOf('__MACOSX') < 0) {
          // 这里就能拿到
          if ((/\.(png|jpg|jpeg|webp|gif)$/).test(fileItem.name)) {
            // png图片
            res.file(fileItem.name)?.async('blob').then(data => {
              dataList.value.push({
                fileName: fileItem.name,
                fileType: '图片',
                fileContent: URL.createObjectURL(data),
              })
            })
          }
          if ((/\.md$/).test(fileItem.name)) {
            // png图片
            res.file(fileItem.name)?.async('string').then(data => {
              dataList.value.push({
                fileName: fileItem.name,
                fileType: 'markdown',
                fileContent: data,

              })
            })
          }
          if ((/\.pdf$/).test(fileItem.name)) {
            // png图片
            res.file(fileItem.name)?.async('blob').then(data => {
              dataList.value.push({
                fileName: fileItem.name,
                fileType: 'pdf',
                fileContent: URL.createObjectURL(data),
              })
            })
          }
        }
      }
    })
  } else {
    console.log('文件不存在,请先上传压缩文件')
  }

}

最终效果:

截屏2024-07-13 22.16.23.png

GitHub Demo地址: github.com/beat-the-bu…