1、Office Web(微软的开发接口)
优点
- 没有 Office也可以直接查看Office 文件
- 适用于移动端、PC
- 无需下载文件就可以在浏览器中查看
<iframe src="文档地址" frameborder="0" />
const docUrl = '外网可预览的地址'
const url = encodeURIComponent(docUrl)
const officeUrl = 'http://view.officeapps.live.com/op/view.aspx?src=' + url
// 在新窗口打开编码后 的链接
window.open(officeUrl, '_target')
const documentUrl = '' // 将此替换为你的Word文档的URL
const officeOnlineViewerUrl = 'https://view.officeapps.live.com/op/view.aspx?src='
// 第一种
// this.previewUrl = officeOnlineViewerUrl + encodeURIComponent(documentUrl)
// 第二种
// this.previewUrl = `${officeOnlineViewerUrl}${documentUrl}&embedded=true`
// 没有下载按钮的--https://view.officeapps.live.com/op/embed.aspx?src=
// 有下载按钮的--https://view.officeapps.live.com/op/view.aspx?src=
2、XDOC文档预览云服务(预览pdf、word、xls、ppt)
注意:文档地址要用utf-8编码,并且外网可访问。
优点:
- 只需要传入文档URL,基于内容自动识别文档格式
- 高效、快速、实时预览,重复请求0毫秒响应
- 使用HTML5方式展现内容,同时适配PC端和移动端
- 支持PDF,OFD,DOC/X,XLS/X,PPT/X,JPG,MP4等多种文档格式
调用方法
https://view.xdocin.com/view?src=文档地址(https://)
eg:
const url = 'https://view.xdocin.com/view?src=文档地址【https(http)://】可预览的地址'
JS调用:
https://view.xdocin.com/view?src=https%3A%2F%2Fview.xdocin.com%2Fdemo%2Fview.docx
可选参数
- &pdf=true,word文档尝试以pdf方式显示,默认false
- &watermark=水印文本,显示文本水印;“img:”+图片url表示图片水印,如:img:https://view.xdocin.com/demo/wm.png
- &saveable=true,是否允许保存源文件,默认false
- &printable=false,是否允许打印,默认true
- ©able=false,是否允许选择复制内容,默认true
- &toolbar=false,是否显示底部工具条,默认true
- &title=自定义标题
- &expire=30,预览链接有效期,单位分钟,默认永久有效
- &limit=,限制页数,如:“5”表示只显示前5页,“2,5”表示从第2页开始的5页,对pdf/doc/docx/ppt/pptx有效
- &filename=文件名,辅助识别文档格式
- &fontsize=字体大小(单位px),默认14,范围:6~58
- &mtime=文件修改时间戳(如:1633093801,精确到秒)或修改时间(如:2021-10-01 21:10:01),值改变刷新缓存
<template>
<iframe
:src="xsrc"
frameborder="0"
scrolling="auto"
style="width:100%;height:100%;"
></iframe>
</template>
<script>
export default {
name: 'XdocView',
data () {
return {
xsrc: ''
}
},
props: {
src: String,
watermark: String
},
watch: {
src: {
handler (val) {
this.genXsrc()
},
immediate: true
},
watermark: {
handler (val) {
this.genXsrc()
},
immediate: true
}
},
methods: {
genXsrc () {
if (this.src) {
// 你的文档地址
const file = this.src
// XDOC文档预览服务地址
let xurl = 'https://view.xdocin.com/view?src='
// 传入文档地址
xurl += encodeURIComponent(file)
// 预览参数
const ops = {
watermark: this.watermark,
// pdf: true, // word文档尝试以pdf方式显示,默认false
// img: true, // 尝试以图片方式显示,默认false
// "saveable": true, //是否允许保存源文件,默认false
printable: false // 是否允许打印,默认true
// "copyable": false, //是否允许选择复制内容,默认true
// toolbar: false // 是否显示底部工具条,默认true
// "expire": 30, //预览链接有效期,单位分钟,默认永久有效
// "limit": "1,3", //限制页数,如:“5”表示只显示前5页,“2,5”表示从第2页开始的5页,对pdf/doc/docx/ppt/pptx有效
// "mtime": 1633093801, //文件修改时间戳(精确到秒)或修改时间(如:2021-10-01 21:10:01),值改变刷新缓存,实时预览
}
// 传入预览参数
for (const a in ops) {
if (ops[a] != undefined) {
xurl += '&' + a + '=' + encodeURIComponent(ops[a])
}
}
// 开始预览
this.xsrc = xurl
}
}
}
}
</script>
<style>
</style>
3、插件预览
安装
//docx文档预览组件
npm install @vue-office/docx vue-demi
//excel文档预览组件
npm install @vue-office/excel vue-demi
//pdf文档预览组件
npm install @vue-office/pdf vue-demi
使用
<template>
<div class="index">
<div class="select-file">
<input style="display: none" id="input" ref="previewRef" type="file">
<el-button size="small" type="primary" @click="uploadBtn">点击上传</el-button>
<el-button size="small" type="primary" @click="previewDoc">
预览文件
</el-button>
</div>
<div class="file-preview">
<!-- Word -->
<VueOfficeDocx
v-if="fileType === 'word'"
style="height: 650px;"
:src="src" />
<!-- Excel -->
<VueOfficeExcel
v-else-if="fileType === 'excel'"
style="height: 650px;"
:src="src" />
<!-- Pdf -->
<VueOfficePdf
v-else-if="fileType === 'pdf'"
style="height: 650px;"
:src="src" />
<!-- img -->
<iframe
v-else-if="fileType === 'image'"
class="iframePreview"
:src="src"
frameborder="0"/>
</div>
</div>
</template>
<script>
import VueOfficeDocx from '@vue-office/docx'
import '@vue-office/docx/lib/index.css'
import VueOfficeExcel from '@vue-office/excel'
import '@vue-office/excel/lib/index.css'
import VueOfficePdf from '@vue-office/pdf'
import axios from 'axios'
import { matchFileType } from '@/utils/tools'
export default {
data () {
return {
src: '',
fileType: ''
}
},
components: {
VueOfficeDocx,
VueOfficeExcel,
VueOfficePdf
},
mounted () {
this.addInputEventListener()
},
methods: {
/*
* application/msword;charset=utf-8
* application/pdf;charset=utf-8
* application/vnd.ms-excel
*/
addInputEventListener () {
const input = document.querySelector('#input')
input.addEventListener('input', e => {
const fileBlob = e.target.files[0]
this.fileType = matchFileType(fileBlob.name)
// 第一种方式(通过window.URL.createObjectURL将Blob文件流转为一个路径)
this.src = window.URL.createObjectURL(new Blob([fileBlob]))
// 第二种方式(转为base64编码)
// const fileReader = new FileReader()
// fileReader.readAsDataURL(fileBlob)
// fileReader.onload = e => {
// this.src = e.target.result
// }
// 第三种方式(获取到buffer)
// fileBlob.arrayBuffer().then(buffer => {
// this.src = buffer
// })
})
},
uploadBtn () {
const previewRef = this.$refs.previewRef
previewRef.click()
},
async previewDoc () {
const URL = window.URL || window.webkitURL
const url = '/upload/handle/2024/01/18/1701677366939-20240118172302.jpg'
this.fileType = matchFileType(url)
const res = await axios({
url,
method: 'get',
responseType: 'blob'
})
try {
const downloadUrl = new Blob([res.data], {
type: res.data.type
})
this.src = URL.createObjectURL(downloadUrl)
} catch (error) {
console.log(error, 'error')
}
}
}
}
</script>
<style>
.index {
width: 100%;
height: 100%;
padding: 15px;
box-sizing: border-box;
}
.select-file {
width: 100%;
border-bottom: 1px dashed #ccc;
margin-bottom: 15px;
}
.file-preview {
width: 100%;
height: 650px;
border: 1px dashed #007acc;
}
.docx-wrapper{
background: none !important;
}
.iframePreview{
width: 100%;
height: 650px;
}
</style>
matchFileType文件
/**
* 根据文件名后缀区分 文件类型
*
* @param: fileName - 文件名称
* @param: 数据返回 1) 无后缀匹配 - false
* @param: 数据返回 2) 匹配图片 - image
* @param: 数据返回 3) 匹配 txt - txt
* @param: 数据返回 4) 匹配 excel - excel
* @param: 数据返回 5) 匹配 word - word
* @param: 数据返回 6) 匹配 pdf - pdf
* @param: 数据返回 7) 匹配 ppt - ppt
* @param: 数据返回 8) 匹配 视频 - video
* @param: 数据返回 9) 匹配 音频 - radio
* @param: 数据返回 10) 其他匹配项 - other
*/
export function matchFileType (fileName) {
// 后缀获取
let suffix = ''
// 获取类型结果
let result = ''
// 路径为空判断
if (!fileName) return false
try {
// 截取文件后缀
suffix = fileName.substr(fileName.lastIndexOf('.') + 1, fileName.length)
// 文件后缀转小写,方便匹配
suffix = suffix.toLowerCase()
} catch (err) {
suffix = ''
}
// fileName无后缀返回 false
if (!suffix) {
result = false
return result
}
const fileTypeList = [
// 图片类型
{ typeName: 'image', types: ['png', 'jpg', 'jpeg', 'bmp', 'gif'] },
// 文本类型
{ typeName: 'txt', types: ['txt'] },
// excel类型
{ typeName: 'excel', types: ['xls', 'xlsx'] },
{ typeName: 'word', types: ['doc', 'docx'] },
{ typeName: 'pdf', types: ['pdf'] },
{ typeName: 'ppt', types: ['ppt'] },
// 视频类型
{ typeName: 'video', types: ['mp4', 'm2v', 'mkv'] },
// 音频
{ typeName: 'radio', types: ['mp3', 'wav', 'wmv'] }
]
for (let i = 0; i < fileTypeList.length; i++) {
const fileTypeItem = fileTypeList[i]
const typeName = fileTypeItem.typeName
const types = fileTypeItem.types
result = types.some(function (item) {
return item === suffix
})
if (result) {
return typeName
}
}
return 'other'
}
4、vue在浏览器局部预览world
1.引入下载
npm i docx-preview@0.1.4
npm i jszip
2.预览在线地址文件
<template>
<div class="home">
<div ref="file"></div>
</div>
</template>
<script>
import axios from "axios";
const docx = require("docx-preview");
window.JSZip = require("jszip");
export default {
mounted() {
axios({
method: "get",
responseType: "blob", // 设置响应文件格式
url: "请求地址",
}).then(({ data }) => {
docx.renderAsync(data, this.$refs.file); // 渲染到页面预览
});
},
};
</script>
3.预览本地文件
<template>
<div class="outbox">
<div class="my-component" ref="preview">
<input type="file" @change="preview" ref="file" />
</div>
</div>
</template>
<script>
window.JSZip = require("jszip");
const docx = require("docx-preview"); // npm i docx-preview@0.1.4
export default {
methods: {
preview(e) {
docx.renderAsync(this.$refs.file.files[0], this.$refs.preview); // 渲染到页面预览
},
},
};
</script>
<style lang="less" scoped>
.outbox {
display: flex;
}
.my-component {
width: 100%;
height: 90vh;
overflow: scroll;
border: 1px solid #000;
}
/* 后面的提示文字颜色 */
[type='file'] {
color: red;
}
/* 主按钮的样式自定义 */
::file-selector-button {
height: 3rem;
font-size: 1rem;
color: #fff;
border-radius: 0.25rem;
border: 1px solid #2a80eb;
padding: 0.75rem 1rem;
background-color: #2a80eb;
box-sizing: border-box;
font-family: inherit;
cursor: pointer;
}
</style>
5、word预览–mammoth.js
npm install --save mammoth
<template>
<div>
<div id="wordView"
v-html="vHtml" />
</div>
</template>
<script>
import mammoth from 'mammoth'
export default {
data () {
return {
vHtml: '',
wordURL: '' // 文件地址
}
},
created () {
const vm = this
const xhr = new XMLHttpRequest()
xhr.open('get', this.wordURL, true)
xhr.responseType = 'arraybuffer'
xhr.onload = function () {
if (xhr.status === 200) {
mammoth
.convertToHtml({ arrayBuffer: new Uint8Array(xhr.response) })
.then(function (resultObject) {
vm.$nextTick(() => {
// document.querySelector("#wordView").innerHTML =
// resultObject.value;
vm.vHtml = resultObject.value
})
})
}
}
xhr.send()
},
methods: {}
}
</script>