经过调研发现,开源库中对docx预览支持较多,doc未找到合适可用的库,包括微软官方js预览插件也仅支持docx。
本篇是对预览组件的封装,可支持docx、jpg、png、txt文件预览
文件预览组件编写
这里以弹窗形式展示预览文件,最终效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| <template> <div class="preview-list"> <iframe v-if="txtUrl" :src="txtUrl" frameborder="0" ></iframe> <el-dialog title="文件预览" v-model="dialogVisible" class="dialog-file" @close="handleCancle" > <div v-if="imgUrl" class="img-prew"> <img :src="imgUrl" alt="" /> </div> <div v-if="docxFile" class="docx-wrap"> <div ref="docxContainer"></div> </div> </el-dialog> </div> </template>
<script lang="ts" setup> import { ElMessage } from 'element-plus' import { getFileType, createUrl } from '@/utils/file' import * as docx from 'docx-preview'
const props = defineProps<{ fileObj: Object }>() const state = reactive({ imgUrl: '', txtUrl: '', docFile: false, docxFile: false, docValue: null }) const { imgUrl, txtUrl, docxFile } = toRefs(state) const dialogVisible = ref(false) const fileTypeMap = { xls: 'application/vnd.ms-excel', xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', doc: 'application/msword', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', pdf: 'application/pdf', png: 'image/png', jpeg: 'image/jpeg', jpg: 'image/jpeg', txt: 'text/plain' } const docxContainer = ref(null)
const handleqaPreviewFileRaw = () => { const fileRaw = props.fileObj.fileRaw const name = props.fileObj.name let suffix = getFileType(name) const type = fileTypeMap[suffix]
if (suffix == 'pdf') { const blob = new Blob([fileRaw], { type }) const url = createUrl(blob) window.open(url) } else if (suffix == 'txt') { const blob = new Blob([fileRaw], { type }) const url = createUrl(blob) state.txtUrl = url dialogVisible.value = true } else if (suffix == 'docx') { state.docxFile = true dialogVisible.value = true nextTick(() => { docx.renderAsync(fileRaw, docxContainer.value).then((x) => console.log('docx: finished', x)) }) } else if (suffix == 'png' || suffix == 'jpg' || suffix == 'jpeg') { const url = createUrl(fileRaw) state.imgUrl = url dialogVisible.value = true } else { ElMessage.info('本文件暂不支持预览,请直接下载后查看,谢谢!') } }
const handlePreviewClear = () => { state.docFile = false state.docxFile = false state.imgUrl = '' state.txtUrl = '' }
const handleCancle = () => { dialogVisible.value = false }
onUnmounted(() => { dialogVisible.value = false }) defineExpose({ handlePreviewClear, handleqaPreviewFileRaw }) </script>
<style lang="scss" scoped> .preview-list { margin-top: 20px; .img-prew { width: 600px; margin: 0 auto; img { width: 100%; } } .docx-wrap { width: 100%; } } </style>
|
文件预览组件使用
| <ul class="filebox"> <li v-for="(file, index) in detail['attachment_info']" :key="index"> <div class="format-file-name">{{ file.name }}</div> <div class="one"> <span class="fileop" @click="handlePreview(file, 'tracechip')">查看</span> </div> </li> </ul> <file-preview ref="fileRef" :fileObj="fileObj"></file-preview>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const handlePreview = (file, name: string) => { lookFile({ attachment_uid: file.uid, bucket_name: name }) .then((res) => { handleqaPreviewFileRaw(res.data, file.name) }) .catch((error) => { console.log(error) }) }
const handleqaPreviewFileRaw = (fileRaw, name) => { fileRef.value.handlePreviewClear() state.fileObj.fileRaw = fileRaw state.fileObj.name = name fileRef.value.handleqaPreviewFileRaw() }
|