vue3文件预览

创建preview-file组件

参考文档:非Vue框架文件预览 | vue-office

  1. pptx文件,点此下载 PPTXjs压缩包,解压后放在public目录下,在index.html中拿到文件url

在PPTXjs/index.html页面,获取传给iframe的动态文件地址

<template>
  <t-dialog :visible="visible" :footer="false" width="100vw" header="文件预览" @close="clickClose">
    <div style="width: 100%; height: calc(80vh - 88px)">
      <!-- word -->
      <div id="docx"></div>
      <!-- excel -->
      <div
        id="xlsx "
        :style="{
          width: fileMessage.excelShow ? '100%' : '',
          height: fileMessage.excelShow ? 'calc(80vh - 88px)' : '',
        }"
      ></div>
      <!--ppt,pptx-->
      <div v-if="fileMessage.pptShow" class="d-flex">
        <iframe
          :src="`PPTXjs-1.21.1/index.html?file=${fileMessage.downloadUrl}`"
          width="100%"
          height="calc(80vh - 88px)"
          frameborder="0"
        ></iframe>
      </div>
      <!--图片-->
      <div v-if="fileMessage.imgShow" class="d-flex">
        <img :src="fileMessage.downloadUrl" />
      </div>

      <!--音频-->
      <div v-else-if="fileMessage.audioShow">
        <!-- loop="loop"  循环播放 -->
        <audio id="myaudio" :src="fileMessage.downloadUrl" controls preload="preload">不支持audio标签</audio>
      </div>

      <!--视频-->
      <div v-else-if="fileMessage.videoShow" class="d-flex">
        <video preload="auto" align="center" controls>
          <source :src="fileMessage.downloadUrl" type="video/mp4" />
        </video>
      </div>
      <!--其他不能预览的-->
      <!-- <div v-else-if="fileMessage.otherShow"></div> -->
    </div>
  </t-dialog>
</template>

<script lang="ts">
import { computed, onMounted, reactive, defineComponent, ref } from 'vue';
import jsPreviewDocx from '@js-preview/docx';
import jsPreviewExcel from '@js-preview/excel';
import '@js-preview/excel/lib/index.css';
import '@js-preview/docx/lib/index.css';
import { MessagePlugin } from 'tdesign-vue-next';

export default defineComponent({
  name: 'PreviewFile',
  props: {
    file: {
      type: Object,
      default: () => {
        return {};
      },
    },
    visible: {
      type: Boolean,
      default: false,
    },
  },
  emits: ['close'],
  setup(props, { emit }) {
    interface FileMessage {
      fileId: string | number;

      fileName: string;

      downloadUrl: string;

      imgShow: boolean;

      docShow: boolean;

      pdfShow: boolean;

      excelShow: boolean;

      audioShow: boolean;

      videoShow: boolean;

      pptShow: boolean;

      // 其他不能预览的
      // otherShow: boolean;
    }

    // interface FileStyle {
    //   height: string;

    //   width: string;
    // }
    // const props = defineProps<Props>();

    // const $emits = defineEmits<Emits>();
    const file = computed(() => props.file);
    // 文件信息
    const fileMessage = reactive<FileMessage>({
      fileId: '',

      fileName: '',

      downloadUrl: '',

      imgShow: false,

      docShow: false,

      excelShow: false,

      audioShow: false,

      videoShow: false,

      // 其他不能预览的
      // otherShow: false,
      pdfShow: false,

      pptShow: false,
    });

    // const fileStyle = reactive<FileStyle>({
    //   height: `${window.innerHeight}px`,
    //   width: '100%',
    // });

    const myDocxPreviewer = ref(null);
    const myXlsxPreviewer = ref(null);

    // 判断文件类型
    const judgeFileType = () => {
      fileMessage.fileName = file.value.fileName;

      fileMessage.downloadUrl = file.value.downloadUrl;

      fileMessage.fileId = file.value.id;

      console.log(fileMessage, 'fileMessage');

      if (
        fileMessage.fileName.endsWith('png') ||
        fileMessage.fileName.endsWith('jpg') ||
        fileMessage.fileName.endsWith('jpeg') ||
        fileMessage.fileName.endsWith('gif')
      ) {
        fileMessage.imgShow = true;
      } else if (fileMessage.fileName.endsWith('docx') || fileMessage.fileName.endsWith('doc')) {
        fileMessage.docShow = true;
      } else if (fileMessage.fileName.endsWith('pdf') || fileMessage.fileName.endsWith('txt')) {
        emit('close');
        window.open(fileMessage.downloadUrl);
      } else if (fileMessage.fileName.endsWith('pptx') || fileMessage.fileName.endsWith('ppt')) {
        fileMessage.pptShow = true;
      } else if (fileMessage.fileName.endsWith('xlsx') || fileMessage.fileName.endsWith('xls')) {
        fileMessage.excelShow = true;
      } else if (fileMessage.fileName.endsWith('mp3')) {
        fileMessage.audioShow = true;
      } else if (fileMessage.fileName.endsWith('mp4')) {
        fileMessage.videoShow = true;
      } else if (fileMessage.fileName.endsWith('zip')) {
        MessagePlugin.warning('压缩文件暂不支持预览,请下载后查看');
        emit('close');
      }
    };
    const clickClose = () => {
      emit('close');
    };
    onMounted(async () => {
      await judgeFileType();
      if (fileMessage.docShow) {
        myDocxPreviewer.value = jsPreviewDocx.init(document.getElementById('docx'));
        myDocxPreviewer.value
          .preview(fileMessage.downloadUrl)
          .then((res) => {
            console.log('预览完成');
          })
          .catch((e) => {
            console.log('预览失败', e);
          });
      } else if (fileMessage.excelShow) {
        myXlsxPreviewer.value = jsPreviewExcel.init(document.getElementById('xlsx'));
        myXlsxPreviewer.value
          .preview(fileMessage.downloadUrl)
          .then((res) => {
            console.log('预览完成');
          })
          .catch((e) => {
            console.log('预览失败', e);
          });
      }
    });
    return {
      fileMessage,
      clickClose,
      // fileStyle,
    };
  },
});
</script>

<style scoped lang="less">
img {
  width: 620px;
  height: 620px;
}

audio {
  width: 100%;
}

video {
  width: 80%;
}

.d-flex {
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>

使用方法:
 

<!-- 文件预览 -->
      <preview-file v-if="previewFiles.fileShow" :visible="previewFiles.fileShow" :file="previewFiles.fileMessage" @close="()=>{
        previewFiles.fileShow = false;
      }" />

### 实现文件预览功能 在 Vue3 项目中实现文件预览功能涉及多个方面,具体取决于要预览文件类型。对于不同类型的文件(如图片、PDF、Word 或 Excel),可以采用不同的方法和技术栈。 #### 图片预览 对于图片文件,可以直接通过 `img` 标签加载并显示: ```html <img :src="imageUrl" alt="Preview Image"> ``` 其中 `imageUrl` 是指向图片资源的 URL 地址[^1]。 #### PDF 文件预览 针对 PDF 文档,可借助第三方库如 pdf.js 来实现在浏览器端渲染 PDF 页面。安装依赖后,在页面内嵌入 `<canvas>` 元素用于展示 PDF 内容,并调用相应 API 加载指定路径下的文档数据流进行绘制[^2]。 另一种更简便的方式是使用在线服务提供的 iframe 嵌套形式快速集成,例如 Google Docs Viewer: ```html <iframe :src="&#39;https://docs.google.com/gview?url=&#39; + encodeURIComponent(pdfUrl)" frameborder="0"></iframe> ``` 此处 `pdfUrl` 表示待查看的目标 PDF 文件地址。 #### Office 类型 (Word/Excel) ##### Word 文件预览 为了处理 Microsoft Word (.doc/.docx),通常会考虑转换为 HTML 或者其他易于呈现的形式再做进一步操作。一种方案是依靠服务器端工具先将 doc(x) 转换成 html 后下发给客户端;另外也可以尝试一些开源 JavaScript 解析器来做即时转换工作,不过这种方式可能面临兼容性和性能挑战。 ##### Excel 文件预览 当涉及到电子表格时,则推荐利用 ant-design-vue 提供的强大组件集配合 SheetJS 库读取 .xls 及其后续版本格式的数据表单内容。首先确保已经引入必要的 npm 包之后,编写类似下面这样的逻辑片段来获取远程 excel 数据源并通过 table 组件直观展现出来[^3]: ```javascript import XLSX from &#39;xlsx&#39;; // ... methods: { async handleFileChange(file){ const resp = await axios.get(&#39;/path/to/excel&#39;, { responseType:&#39;arraybuffer&#39; }); const workbook = XLSX.read(resp.data, {type:"array"}); this.tableData = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]); } } ``` 此外,考虑到实际应用场景中的复杂度以及安全性考量,有时还需要额外设置代理接口解决跨域资源共享(CORS)等问题,特别是在 Nuxt3 这样的框架下可以通过创建自定义事件处理器简化这一过程[^4]。 综上所述,根据不同种类的文件选择合适的技术手段能够有效提升用户体验的同时也降低了开发难度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值