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文件的预览图

总结

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

相关推荐
庸俗今天不摸鱼几秒前
Canvas进阶-4、边界检测(流光,鼠标拖尾)
开发语言·前端·javascript·计算机外设
bubusa~>_<24 分钟前
解决npm install 出现error,比如:ERR_SSL_CIPHER_OPERATION_FAILED
前端·npm·node.js
流烟默1 小时前
vue和微信小程序处理markdown格式数据
前端·vue.js·微信小程序
梨落秋溪、1 小时前
输入框元素覆盖冲突
java·服务器·前端
菲力蒲LY2 小时前
vue 手写分页
前端·javascript·vue.js
天下皆白_唯我独黑2 小时前
npm 安装扩展遇到证书失效解决方案
前端·npm·node.js
~欸嘿2 小时前
Could not download npm for node v14.21.3(nvm无法下载节点v14.21.3的npm)
前端·npm·node.js
化作繁星3 小时前
React 高阶组件的优缺点
前端·javascript·react.js
zpjing~.~3 小时前
vue 父组件和子组件中v-model和props的使用和区别
前端·javascript·vue.js
做一颗卷心菜3 小时前
Promise
开发语言·前端·javascript