![](https://img-blog.csdnimg.cn/img_convert/a54d506de434f3b15b1f40406a59d8f2.png)
依赖: ant-design-vue,@ant-design/icons-vue ,docx-preview
上传组件:ant design vue的upload
预览组件: docx-preview
单文件上传+浏览
思路
上传组件默认会帮用户发送请求,但是我不想用这个功能。。。看API,beforeUpload属性可以传入方法,每次选择文件后都会被调用。如果这个方法return false就会阻止后续的上传(相当于让我们自己去手动上传)
在这个方法里,我想:
读取刚刚上传的文件
把文件转化成docx-preview组件能接受的形式
渲染docx-preview的dom元素
最后return false,阻止组件的自动发送请求
步骤1可以直接通过beforeUpload方法的传参获取;步骤34照着组件api抄就完事。
难点还是步骤2:获取的是File类型,需要转换为Blob类型。鼓捣了一阵后,我发现一种可以实现的方式是File -> Base64 -> Blob。(参考文档:Base64、Blob、File ,dataUrl 相互转化三种类型的相互转换)
示例
<script setup>
import { ref } from 'vue'
import { InboxOutlined } from '@ant-design/icons-vue'
import { renderAsync } from 'docx-preview'
const fileList = ref([])
const fileBlob = ref(null)
const beforeUpload = file => {
const fileReader = new FileReader()
fileReader.readAsDataURL(file)
fileReader.onload = (e) => {
const dataURL = e.target.result
const arr = dataURL.split(',')
const defaultMimeType = arr[0].match(/:(.*?);/)[1]
const bStr = atob(arr[1])
let n = bStr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bStr.charCodeAt(n)
}
const blob = new Blob([u8arr], { type: file.type || defaultMimeType })
fileBlob.value = blob
renderAsync(blob, document.getElementById('doc-container'), null, {
className: 'docx', // 默认和文档样式类的类名/前缀
inWrapper: true, // 启用围绕文档内容渲染包装器
ignoreWidth: false, // 禁止页面渲染宽度
ignoreHeight: false, // 禁止页面渲染高度
ignoreFonts: false, // 禁止字体渲染
breakPages: true, // 在分页符上启用分页
ignoreLastRenderedPageBreak: true, //禁用lastRenderedPageBreak元素的分页
experimental: false, //启用实验性功能(制表符停止计算)
trimXmlDeclaration: true, //如果为真,xml声明将在解析之前从xml文档中删除
debug: false // 启用额外的日志记录
})
}
return false
}
</script>
<template>
<div>
<a-upload-dragger
v-model:fileList="fileList"
name="file"
accept=".docx"
:before-upload="beforeUpload"
:max-count="1"
>
<p class="ant-upload-drag-icon">
<inbox-outlined></inbox-outlined>
</p>
<p class="ant-upload-text">点击或拖拽文件到此处</p>
<p class="ant-upload-hint">(最大上传文件数:1)</p>
</a-upload-dragger>
<div id="doc-container"></div>
</div>
</template>
多文件上传+浏览
上传组件里的max-count属性改为文件上限,这样这个组件就能接受多个文件同时上传了。
beforeUpload里还是一样转换刚刚上传的文件,然后把Blob保存到某个ref里。再根据自己的需求去决定用哪个blob渲染预览的dom(甚至可以渲染多个dom同时展示多个文件)。
另外,上传组件里的fileList保存的是已上传文件列表,包含每个文件的信息。比如fileList.value[0].name就是第一个文件的名称(不包括后缀)。更多信息可以直接把这个列表打印出来自己看。