vue3 封装图片上传预览组件支持docx、excel、pdf、图片、txt格式

主要是使用vue-office来实现docx和excel、pdf插件来实现预览

插件下载插件

javascript 复制代码
npm i @vue-office/docx
npm i @vue-office/excel
npm i @vue-office/pdf
javascript 复制代码
<script setup lang="ts">
//引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'
//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
//引入VueOfficePdf组件
import VueOfficePdf from '@vue-office/pdf'
import * as FileApi from '@/api/system/file'
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false)
const src = ref('')
const docx = ref('')
const excel = ref('')
const pdf = ref('')
const txt = ref('')
const fileObj = ref<{ fileFormat: string; fileName: string }>({
  fileFormat: '',
  fileName: ''
})
let fileInfo
let fileUrl
const renderedHandler = () => {
  formLoading.value = false
}
const errorHandler = () => {
  formLoading.value = false
}
const open = async (data: any, url: string) => {
  src.value = ''
  docx.value = ''
  excel.value = ''
  pdf.value = ''
  txt.value = ''
  fileInfo = data
  dialogVisible.value = true
  formLoading.value = true
  fileObj.value = await FileApi.getuploadInfo(url)
  fileUrl = await FileApi.getDownloadUrl(url)
  if (fileUrl) {
    try {
      if (
        fileObj.value.fileFormat === 'jpeg' ||
        fileObj.value.fileFormat === 'jpg' ||
        fileObj.value.fileFormat === 'png'
      ) {
        src.value = fileUrl
        formLoading.value = false
      } else {
        if (fileObj.value.fileFormat === 'xlsx' || fileObj.value.fileFormat === 'xls') {
          excel.value = fileUrl
        } else if (fileObj.value.fileFormat === 'docx') {
          docx.value = fileUrl
        } else if (fileObj.value.fileFormat === 'pdf') {
          pdf.value = fileUrl
        } else if (fileObj.value.fileFormat === 'txt') {
          try {
            const response = await fetch(fileUrl)
            txt.value = await response.text()
            formLoading.value = false
          } catch (e) {
            console.log(e)
            formLoading.value = false
          }
        } else {
          formLoading.value = false
        }
        console.log('fileObj.value.fileFormat', fileObj.value.fileFormat)
      }
    } finally {
      // formLoading.value = false
    }
  }
}
const close = () => {
  dialogVisible.value = false
}
const handleDownload = async () => {
  if (!fileUrl) {
    return
  }
  const response = await fetch(fileUrl)
  if (!response.ok) {
    message.success(t('common.downloadFail'))
  }
  const blob = await response.blob()
  const url = URL.createObjectURL(blob)

  const a = document.createElement('a')
  a.href = url
  a.download = fileInfo.fileName || fileObj.value.fileName + '.' + fileObj.value.fileFormat
  a.click()
}
defineExpose({
  open
})
</script>

<template>
  <Dialog v-model="dialogVisible" @close="close" width="900px" :destroy-on-close="true">
    <div class="preview-content" v-loading="formLoading">
      <img
        :src="src"
        alt=""
        style="width: 100%"
        v-if="
          fileObj.fileFormat === 'jpeg' ||
          fileObj.fileFormat === 'jpg' ||
          fileObj.fileFormat === 'png'
        "
      />
      <template v-else>
        <vue-office-docx
          :src="docx"
          v-if="docx"
          style="width: 100%; height: 100%"
          @rendered="renderedHandler"
          @error="errorHandler"
        />
        <vue-office-excel
          :src="excel"
          v-if="excel"
          style="width: 100%; height: 100%"
          @rendered="renderedHandler"
          @error="errorHandler"
        />
        <vue-office-pdf
          :src="pdf"
          v-if="pdf"
          style="width: 100%; height: 100%"
          @rendered="renderedHandler"
          @error="errorHandler"
        />
        <div v-if="txt">{{ txt }}</div>
        <span v-if="!docx && !excel && !pdf && !txt">文件类型暂不支持预览</span>
      </template>
    </div>
    <template #icon>
      <Icon class="is-hover mr-10px cursor-pointer" icon="ep:download" @click="handleDownload" />
    </template>
  </Dialog>
</template>

<style scoped lang="scss">
.preview-content {
  position: relative;
  width: 100%;
  height: 600px;
  overflow: hidden;
}
</style>
相关推荐
2601_962381864 小时前
Python办公联动:Excel数据一键自动生成PPT图表
python·数据分析·自动化·excel·ppt
OpenTiny社区4 小时前
从流式消息到多会话:TinyRobot Kit 如何组织 AI 对话数据层
vue.js
卤蛋fg66 小时前
vue表格组件 vxe-table 鼠标滑动表头选择整列与选择整行的配置详解
vue.js
阳火锅7 小时前
老板要周报?我说不用,代码提交就是进度
前端·javascript·vue.js
简单Janeee11 小时前
[Vue 3 从零到上线]-第九篇:更美更强——引入 UI 库与网络请求 (Axios)
网络·vue.js·ui
小蒜学长11 小时前
基于SpringBoot + Vue的智能健身房管理系统的设计与实现(代码+数据库+LW)
java·数据库·vue.js·spring boot·后端
eybk11 小时前
python将图片pdf文件转为透明文字的pdf文件
pdf
千里码aicood13 小时前
Django+Vue 基于XGBoost与随机森林的沿海地区台风天气大数据预警系统实现
vue.js·随机森林·django
jay神14 小时前
【计算机毕业设计】基于Flask+Vue的电影数据可视化与智能推荐系统
前端·vue.js·python·信息可视化·flask·毕业设计·课程设计
小新科研测评1 天前
2026 年 3 种 PDF 文献翻译方案横评:公式/表格/双栏排版保真度实测
人工智能·ai·pdf·自动翻译