Vue3+Element Plus实现文件预览和下载功能(.docx,.pdf,.md)

前言

文档预览和下载功能在后台管理系统中还是挺常见的,最近就碰上了这个需求,记录一下我是怎么做的吧。

安装与引入

用到的是vue-office库,一种支持多种文件(docx、excel、pdf)预览的 vue 组件库(由于项目没用到execel,所以就没做,不过用法都一样)。

typescript 复制代码
//docx文档预览组件
npm install @vue-office/docx

//pdf文档预览组件
npm install @vue-office/pdf

//引入(pdf好像没有css文件,不用引)
import VueOfficeDocx from '@vue-office/docx'
import VueOfficePdf from '@vue-office/pdf'
import '@vue-office/docx/lib/index.css'

实现代码

接口代码

要发两次请求,第一次是上传文件到后端,第二次是从后端下载文件。下载文件时需要注意的是后端返回的是文件流,在请求时需要多加一个参数 responseType:'blob,否则等等下载的文件会出现乱码。(刚开始感觉这接口地址怪怪的,半天没弄懂参数是什么,实际上就是请求第一次上传文件成功后,后端返回的地址(需要截取一下,只要后半段)。像这样:'infra/file/5/get/测试文档1.docx')

vbnet 复制代码
//这是文档上的下载文件的接口地址,admin-api是baseURL
GET:/admin-api/infra/file/{configId}/get/**

// 下载文件
export const downloadFile = async (configId: string) => {
  return await request.get2({ url: `${configId}`, responseType: 'blob' })
}

vue代码

我是将预览内容显示在对话框中的,通过点击预览按钮展开对话框。

xml 复制代码
<template>
    <el-dialog v-model="dialogTwoVisible" title="文件预览" width="800" align-center fullscreen>
        <!-- docx -->
        <vue-office-docx v-if="fileType == 'docx'" :src="src" />
        <!-- pdf -->
        <vue-office-pdf v-if="fileType == 'pdf'" :src="src" />
        <!-- md -->
        <div v-if="fileType == 'md'" :src="src" id="markdown-preview" v-html="html"></div>
     </el-dialog>
  </template>
 
<script lang="ts" setup>

import * as DetailApi from '@/api/algorithm/detail/index'
import MarkdownIt from 'markdown-it'

const dialogTwoVisible = ref(false) // 预览弹窗的是否展示
const html = ref() //.md文件要用到的
const fileName = ref() //文件名
const fileType = ref('') //文件类型
const src = ref('') //word和pdf文件要用到的
const formData = ref({
  apiDocUrl: ''     //文件上传成功后后端返回的data
})                  //长这样:"http://10.3.2.243:48088/admin-api/infra/file/5/get/测试文档1.docx"

//获取文件名
const getFileName = (fileUrl: string) => {
  const arr = fileUrl.split('/')
  fileName.value = arr[arr.length - 1]
  fileType.value = fileName.value.split('.')[1]
}

//预览按钮的回调函数
const onPreview = async () => {
  //释放临时URL
  URL.revokeObjectURL(src.value)
  //获取文件下载请求路径
  let str = formData.value.apiDocUrl
  getFileName(str)
  //这边是需要发请求,请求的地址就是:/infra/file/5/get/测试文档1.docx
  let startIndex = str.indexOf('http://10.3.2.243:48088/admin-api') // 获取指定字符串的起始位置
  if (startIndex !== -1) {
    let newStr = str.slice(startIndex + 'http://10.3.2.243:48088/admin-api'.length) // 获取起始位置之后的内容
    const downloadFile = await DetailApi.downloadFile(newStr)
    //返回一个新的blob对象
    const blob = new Blob([downloadFile])
    if (fileType.value === 'md') {
      //将文件内容读入内存
      const reader = new FileReader()
      //读取完成后触发
      reader.onload = () => {
        const markdownText = reader.result
        const md = new MarkdownIt()
        //将markdown文件转换为html页面展示
        html.value = md.render(markdownText)
      }
      //异步按字符读取文件内容,结果用字符串形式表示
      reader.readAsText(blob)
    } else {
      if (fileType.value === 'pdf') {
        const file = new File([blob], fileName.value, {
          type: 'application/pdf'
        })
        src.value = URL.createObjectURL(file)
      } else {
        const file = new File([blob], fileName.value, {
          type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        })
        src.value = URL.createObjectURL(file)
      }
    }
  }
  dialogTwoVisible.value = true
}

//下载按钮的回调函数
const handleDownload = () => {
  window.open(formData.value.apiDocUrl)
}
</script>

效果图

接口文档是一个弹窗中form表单的一必填项,通过点击预览按钮打开第二个弹窗

word和pdf文件的预览看上去都差不多

下面是markdown文件的预览图

总结

前端实现文件预览和下载还是比较常见的需求,上面只是完成了基本的功能,但肯定还有更好的解决方法。功能实现后回顾感觉也不是很难,但刚开始做的时候总会各种卡壳,时间也拖了挺久。个人反思主要还是工作经验太少,相信随着工作经验的积累以后的开发速度会越来越快。

相关推荐
小白学习日记43 分钟前
【复习】HTML常用标签<table>
前端·html
丁总学Java1 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele1 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范
懒羊羊大王呀2 小时前
CSS——属性值计算
前端·css
DOKE2 小时前
VSCode终端:提升命令行使用体验
前端
xgq2 小时前
使用File System Access API 直接读写本地文件
前端·javascript·面试
用户3157476081352 小时前
前端之路-了解原型和原型链
前端
永远不打烊2 小时前
librtmp 原生API做直播推流
前端
北极小狐2 小时前
浏览器事件处理机制:从硬件中断到事件驱动
前端
无咎.lsy2 小时前
vue之vuex的使用及举例
前端·javascript·vue.js