二进制流进行预览pdf、excel、docx
安装
@vue-office/docx
:Word文档预览组件@vue-office/excel
:Excel文档预览组件@vue-office/pdf
:PDF文档预览组件#docx文档预览组件 npm install @vue-office/docx vue-demi#excel文档预览组件 npm install @vue-office/excel vue-demi#pdf文档预览组件 npm install @vue-office/pdf vue-demi
引入
import VueOfficePdf from '@vue-office/pdf/lib/v3' import VueOfficeDocx from '@vue-office/docx/lib/v3' import VueOfficeExcel from '@vue-office/excel/lib/v3' import '@vue-office/docx/lib/v3/index.css' import '@vue-office/excel/lib/v3/index.css'
使用
<el-dialogv-model="previewDialogVisible":title="previewFileName"width="80%"height="80%"top="5vh":before-close="handlePreviewClose"destroy-on-close><div class="preview-container"><div class="preview-info"><!-- 加载状态 --><div v-if="loadingPreview" class="loading-container"><el-skeleton animated><template #template><el-skeleton-item variant="p" style="height: 300px" /></template></el-skeleton><p style="text-align: center; margin-top: 20px;">文件加载中...</p></div><!-- 2. 错误状态(加载失败时显示) --><div v-else-if="previewError" class="error-container"><el-icon color="#f56c6c" size="48" style="margin-bottom: 16px;"><CircleCloseFilled /></el-icon><p style="color: #f56c6c;">{{ previewError }}</p></div></div><!-- PDF文件预览 --><VueOfficePdfv-if="currentPreviewData?.fileType === 'pdf'":src="previewFileUrl"class="pdf-preview"@rendered="renderedHandler"@error="errorHandler"style="height: 70vh;"/><!-- docx文件预览 --><vue-office-docxv-else-if="['docx', 'doc'].includes(currentPreviewData?.fileType)":src="previewFileUrl"style="height: 70vh;"@rendered="renderedHandler"@error="errorHandler"/><!-- excel文件预览 --><vue-office-excelv-else-if="['xlsx', 'xls'].includes(currentPreviewData?.fileType)":src="previewFileUrl":options="options"style="height: 70vh;"@rendered="renderedHandler"@error="errorHandler"/><!-- 4. 不支持的文件格式(无匹配时显示) --><div v-else class="unsupported-container"><el-icon color="#909399" size="48" style="margin-bottom: 16px;"><InfoFilled /></el-icon><p style="color: #909399;">不支持当前文件格式({{ currentPreviewData?.fileType || '未知' }}),请点击"下载文件"查看</p></div></div><template #footer><div class="dialog-footer"><el-button @click="handlePreviewClose">关闭</el-button> <!-- <el-button type="primary" @click="handleDownloadCurrentFile">下载文件</el-button>--></div></template></el-dialog>
通过二进制流转换成本地Blob文件 url 进行预览
// 获取文件扩展名
const getFileExtension = (fileName) => {if (!fileName) return ''return fileName.slice(((fileName.lastIndexOf('.') - 1) >>> 0) + 2).toLowerCase()
}// 名称点击事件
const handlePrintArchiveName = async (rowData) => {console.log(rowData.fileType)// 检查是否有预览权限if (!permission.value.download) {ElMessage.warning('您没有预览权限')return}// 检查是否有所需的文件信息if (!rowData.importFullFilePath && !rowData.filePath) {ElMessage.warning('文件信息不完整,无法预览')return}try {// 重置状态loadingPreview.value = truepreviewError.value = ''currentPreviewData.value = rowDatapreviewFileName.value = rowData.archiveName || '文件预览'let quryDomainUrl = changeUrl('xzspknowledgearchive', 'common/xzspknowledgearchive/downloadfile')const response = await commonPosts(quryDomainUrl, {businessFlg: 'download',moduleName: 'xzspknowledgearchive',uniqueId: rowData.uniqueId,fileName: rowData.filePath}, {repeatSubmit: false, // 按需传递防重复提交参数responseType: 'blob' // 关键:指定响应类型为 blob})// 5. 生成本地预览URL(核心步骤)const fileExt = getFileExtension(rowData.filePath)const mimeType = getMimeTypeByExt(fileExt)// 用正确的 MIME 类型重新包装 Blob(解决类型缺失问题)const fileBlob = new Blob([response], { type: mimeType })previewFileUrl.value = URL.createObjectURL(fileBlob)// 显示预览弹窗previewDialogVisible.value = true// 延迟关闭加载状态,给文件一些加载时间setTimeout(() => {loadingPreview.value = false}, 1000)} catch (error) {console.error('预览失败:', error)loadingPreview.value = falsepreviewError.value = '文件预览失败,请重试'ElMessage.error('文件预览失败,请重试')}
}// 新增:根据文件后缀获取 MIME 类型的工具函数
const getMimeTypeByExt = (ext) => {const mimeMap = {// Office 文档xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',xls: 'application/vnd.ms-excel',docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',doc: 'application/msword',// 其他常见类型pdf: 'application/pdf',txt: 'text/plain',zip: 'application/zip'}return mimeMap[ext.toLowerCase()] || 'application/octet-stream' // 默认二进制类型
}// PDF渲染完成回调
const renderedHandler = () => {console.log('PDF渲染完成')loadingPreview.value = false
}// PDF渲染错误回调
const errorHandler = (error) => {console.error('PDF渲染失败:', error)loadingPreview.value = falsepreviewError.value = 'PDF文件渲染失败,请尝试下载查看'
}// 关闭预览弹窗
const handlePreviewClose = () => {previewDialogVisible.value = falsepreviewFileUrl.value = ''previewFileName.value = ''currentPreviewData.value = nullloadingPreview.value = falsepreviewError.value = ''
}