前言
最近开发接到一个需要在线预览各种文件,没有文件服务器,后端直接返回文件流,前端处理进行在线预览的需求。文件类型分别有图片、pdf、docx、excel,作为一个菜鸟来记录一下啦,有不对的地方希望大家可以指导指导。
一、 图片预览
// 处理从接口返回的文件流
let that = this
// 读取文件
let reader = new FileReader()
// 文件读取成功完成时
reader.onload = function( event ) {
try {
that imgSrc = event.target.result
}catch(error){
let jsonData = JSON.parse(reader.result)
that.$message.error(JSONData.msg)
}
reader.readAsDataUrl(res.data)
}
二、 docx预览
使用docx-preview插件进行预览docx文件,这个插件不能预览doc文件。使用npm安装: npm install docx-preview --save
<template>
<div>
<div ref="word"></div>
</div>
</template>
<script>
let docx = require('docx-preview')
export default {
data(){
return {
fileId: ''
}
},
methods: {
// 请求接口下载文件
downloadFile(){
request({
method: 'get',
params: {fileId: this.fileId},
url: url, // 下载文件接口地址
// 文件流
responseType: 'blob',
}).then(res => {
// 渲染在界面上
docx.renderAsync(res.data, this.$refs.word).then(res => {})
})
}
}
}
</script>
三、pdf预览
pdf预览一开始使用的是vue-pdf预览,后面系统从windows服务器更换到linux服务器后vue-pdf打包上线后预览报错,本地是没有问题的,试过更换插件版本不行,重新安装插件发现服务器上项目下的node_modules文件里的vue-pdf文件不一样。最后改成使用iframe进行在线预览。目前还不知道什么什么原因,若有知道的jym可以帮忙解答一下。上线之后报错预览报错截图:
1. vue-pdf预览,npm安装:npm install vue-pdf --save
<template>
<div class="pdf-content">
<div v-if="src">
<!-- 循环显示pdf内容 -->
<pdf v-for="i in numsPage" :key="i" :src="pdfSrc
" :page="i"></pdf>
</div>
</div>
</template>
<script>
// 引入vue-pdf组件
import pdf from 'vue-pdf'
import { preview } from '@/utils/download'
export default {
// 注册pdf组件
components: { pdf },
data() {
return {
src: '',
numsPage: 0,
fileId: ''
}
},
computed: {
// 解决PDF中文字体丢失的问题
pdfSrc(){
let src = pdf.createLoadingTask({
url: this.src,
// 引入字体
cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.5.207/cmaps/',
cMapPacked: true
})
return src
}
}
created() {
this.fileId = this.$route.query.fileId
preview(this.fileId).then(res => {
this.src = res
console.log('文件', this.src);
// 获取pdf页码
this.getPageNums()
}).catch(() => {})
},
methods: {
getPageNums() {
let loadingTask = pdf.createLoadingTask(this.src)
loadingTask.promise.then(pdf => {
this.numsPage = pdf.numPages
}).catch(() => {})
}
}
}
</script>
<style lang="scss" scoped>
.pdf-content {
width: 100%;
height: 100%;
}
</style>
download.js
export function preview(fileId, filename, responseType) {
return new Promise((resolve, reject) => {
request({
method: 'get',
params: {
fileId,
},
url: '/file/download',
responseType: responseType ? responseType : 'blob',
timeout: 0
}).then(res => {
let url = getUrl(res, filename) || ''
// 返回Url
resolve(url)
}).catch((error) => {
reject(error)
});
})
}
function getUrl(res, fileName) {
let blob = new Blob([res.data], {type: 'application/pdf;charset-UTF-8'})
let url = URL.createObjectURL(blob)
return url
}
2. iframe预览
<template>
<div>
<iframe :scr="pdf文件下载地址"></iframe>
</div>
</template>
四、excel预览
使用xlsx插件进行excel预览,npm安装:nmp insatll xlsx --save
<template>
<div>
<el-tabs type="card" v-model="tableIndex">
// 遍历工作表
<el-tab-pane v-for="(item, index) in tableNums" :key="index" :label="item" :name="index">
<div v-html="xlsxData"></div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<Script>
import request from './request'
import xlsx from 'xlsx'
export default {
data(){
return {
xlsxData: '',
fileId: '',
fileName: '',
tableNums: [],
tableIndex: 0,
excelData: null,
}
},
watch: {
// 动态渲染工作表
tableIndex(val) {
this.renderExcel()
}
},
created() {
this.fileId = this.$route.query.fileId
this.fileName = this.$route.query.fileName
this.downloadFile()
},
methods: {
downloadFile(){
request({
method: 'get',
params: {
fileId: this.fileId,
},
url: url,
// arraybuffer
responseType: 'arraybuffer',
timeout: 0
}).then(res => {
this.excelData = res.data
this.renderExcel()
}).catch((error) => {})
},
// 渲染
renderExcel(){
if(this.excelData) {
// 解析数据
let workbook = xlsx.read(new Unit8Array(this.excelData), { type:'array' })
this.tableNums = workbook.sheetNames
// workbook.sheetNames存这每个工作表的名字
let worksheet = workboot.Sheets[workboot.SheetNames[this.tableIndex]]
// 渲染
this.xlsxData = xlsx.utils.sheet_to_html(worksheet)
}
}
}
}
</script>