vue2.0纯前端预览附件方法汇总
程序媛_MISS_zhang_0110 2024-09-03 15:33:01 阅读 73
vue2.0纯前端预览附件方法汇总
一、使用iframe预览1.使用 Office 在线查看器2.XDOC文档预览服务XDOC官网地址:[https://view.xdocin.com/](https://view.xdocin.com/)
二、vue-office具体效果可以参考: [https://501351981.github.io/vue-office/examples/dist/#/docx](https://501351981.github.io/vue-office/examples/dist/#/docx)
1.docx预览2.excel文档预览3.pdf文档预览具体代码可以参考: [https://gitee.com/ye-jizeng/vue-office#https://gitee.com/link?target=https%3A%2F%2F501351981.github.io%2Fvue-office%2Fexamples%2Fdist%2F](https://gitee.com/ye-jizeng/vue-office#https://gitee.com/link?target=https%3A%2F%2F501351981.github.io%2Fvue-office%2Fexamples%2Fdist%2F)
三、file-viewer插件(封装好的预览组件)1.通过上传获取文件arrayBuffer具体效果可以参考: [https://zhuye1993.github.io/file-view/dist/index.html](https://zhuye1993.github.io/file-view/dist/index.html)代码地址: [https://github.com/zhuye1993/file-view](https://github.com/zhuye1993/file-view)
2.通过上传获取文件arrayBuffer和Url方式(都转换成html 和css方式)具体效果可以参考: [https://viewer.flyfish.group/](https://viewer.flyfish.group/)代码地址:[https://git.flyfish.dev/flyfish-group/file-viewer-demo](https://git.flyfish.dev/flyfish-group/file-viewer-demo)
四、vue-pdf插件1.全文预览2.指定页数,直接预览到某页的
五、pptx.js插件
一、使用iframe预览
1.使用 Office 在线查看器
支持 Word 和 Excel 和Pdf 文档预览,兼容性好。不需要额外安装库,直接使用在线服务。 文件地址必须公网
<code><iframe :src="textVisibleURl" frameborder="0" width="700" height="800"></iframe>code>
// 打开文件预览
clickPreview(pitem) { -- -->
if (/\.pdf$/i.test(pitem.name)) {
this.textVisibleURl = pitem.url;
} else if (/\.(doc|docx|xls|xlsx|ppt|pptx|pdf)$/i.test(pitem.name)) {
let src = pitem.url;
//这个地址预览的时候有一些按钮
// this.textVisibleURl = `https://view.officeapps.live.com/op/view.aspx?src=${src}`;
this.textVisibleURl = `https://view.officeapps.live.com/op/embed.aspx?src=${ src}`;
} else if (/\.csv$/i.test(pitem.name)) {
this.textVisibleURl = `http://view.xdocin.com/xdoc?_xdoc=${ pitem.url}`;
}
},
2.XDOC文档预览服务
调用方法:https://view.xdocin.com/view?src=你的文档地址
<iframe
class="iframeDom"code>
:src="textVisibleURl"code>
frameborder="0"code>
width="100%"code>
height="800"code>
></iframe>
clickPreview(){ -- -->
var xurl = 'https://view.xdocin.com/view?src=';
xurl += encodeURIComponent(newV);
let ops = {
pdf: true,
// toolbar: false,
// limit: '2,1', //只显示第二页code>
// limit: '2', //显示一二页
limit: '5,4', //显示一二页
// limit: '2,3', //显示二三四页
};
for (var a in ops) { -- -->
xurl += '&' + a + '=' + encodeURIComponent(ops[a]);
}
this.textVisibleURl = xurl;
}
XDOC官网地址:https://view.xdocin.com/
二、vue-office
支持多种文件(.docx、.pdf、.excel)预览的vue组件套装,支持vue2/3。
只需提供文档的src(网络地址)即可完成文档预览
(其中word是转换成html 和css,可以对文档内容进行高亮定位什么的)
有文档网络地址,比如 https://***.docx
文件上传时预览,此时可以获取文件的ArrayBuffer或Blob
具体效果可以参考: https://501351981.github.io/vue-office/examples/dist/#/docx
//docx文档预览组件
npm install @vue-office/docx vue-demi
//excel文档预览组件
npm install @vue-office/excel vue-demi
//pdf文档预览组件
npm install @vue-office/pdf vue-demi
1.docx预览
// 使用网络地址
<template>
<vue-office-docx :src="docx" @rendered="rendered"/>code>
</template>
<script>
//1.引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'
export default { -- -->
components:{
VueOfficeDocx
},
data(){
return {
docx: 'http://static.shanhuxueyuan.com/test6.docx' //设置文档网络地址,可以是相对地址
}
},
methods:{
rendered(){
console.log("渲染完成")
}
}
}
</script>
//********************************************************************************************
//2.element的上传组件,获取文件的arrayBuffer
<template>
<div id="docx-demo">code>
<el-upload :limit="1" :file-list="fileList" accept=".docx" :beforeUpload="beforeUpload" action="">code>
<el-button size="small" type="warning">点击上传</el-button>code>
</el-upload>
<vue-office-docx :src="src" />code>
</div>
</template>
<script>
import VueOfficeDocx from '@vue-office/docx'
import '@vue-office/docx/lib/index.css'
export default { -- -->
components: {
VueOfficeDocx
},
data(){
return {
src:'',
fileList:[]
}
},
methods:{
beforeUpload(file){
let reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = (loadEvent) => {
let arrayBuffer = loadEvent.target.result;
this.src = arrayBuffer
};
return false
}
}
}
</script>
//********************************************************************************************
//3.原生的input type="file"code>
<template>
<div>
<input type="file" @change="changeHandle"/>code>
<vue-office-docx :src="src"/>code>
</div>
</template>
<script>
import VueOfficeDocx from '@vue-office/docx'
import '@vue-office/docx/lib/index.css'
export default { -- -->
components: {
VueOfficeDocx
},
data(){
return {
src: ''
}
},
methods:{
changeHandle(event){
let file = event.target.files[0]
let fileReader = new FileReader()
fileReader.readAsArrayBuffer(file)
fileReader.onload = () => {
this.src = fileReader.result
}
}
}
}
</script>
2.excel文档预览
<template>
<vue-office-excel :src="excel" @rendered="rendered"/>code>
</template>
<script>
//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
export default { -- -->
components:{
VueOfficeExcel
},
data(){
return {
excel: 'http://static.shanhuxueyuan.com/demo/excel.xlsx'//设置文档地址
}
},
methods:{
rendered(){
console.log("渲染完成")
}
}
}
</script>
3.pdf文档预览
<template>
<vue-office-pdf :src="pdf" @rendered="rendered"/>code>
</template>
<script>
//引入VueOfficePdf组件
import VueOfficePdf from '@vue-office/pdf'
export default { -- -->
components:{
VueOfficePdf
},
data(){
return {
pdf: 'http://static.shanhuxueyuan.com/test.pdf' //设置文档地址
}
},
methods:{
rendered(){
console.log("渲染完成")
}
}
}
</script>
具体代码可以参考: https://gitee.com/ye-jizeng/vue-office#https://gitee.com/link?target=https%3A%2F%2F501351981.github.io%2Fvue-office%2Fexamples%2Fdist%2F
三、file-viewer插件(封装好的预览组件)
1.通过上传获取文件arrayBuffer
具体效果可以参考: https://zhuye1993.github.io/file-view/dist/index.html
代码地址: https://github.com/zhuye1993/file-view
参考文章链接: https://juejin.cn/post/7071598747519549454
// 主要代码
<template>
<div :class="{ hidden }">code>
<div class="banner">code>
<div class="container">code>
<h1>
<div>
在线文档查看
<input class="file-select" type="file" @change="handleChange" />code>
</div>
</h1>
</div>
</div>
<div class="container">code>
<div v-show="loading" class="well loading">正在加载中,请耐心等待...</div>code>
<div v-show="!loading" class="well" ref="output"></div>code>
</div>
</div>
</template>
<script>
import { -- --> getExtend, readBuffer, render } from "@/components/util";
import { parse } from "qs";
/**
* 支持嵌入式显示,基于postMessage支持跨域
* 示例代码:
*
*/
export default {
name: "HelloWorld",
props: {
msg: String,
},
data() {
return {
// 加载状态跟踪
loading: false,
// 上个渲染实例
last: null,
// 隐藏头部,当基于消息机制渲染,将隐藏
hidden: false,
};
},
created() {
// 允许使用预留的消息机制发送二进制数据,必须在url后添加?name=xxx.xxx&from=xxx
const { from, name } = parse(location.search.substr(1));
if (from) {
window.addEventListener("message", (event) => {
const { origin, data: blob } = event;
if (origin === from && blob instanceof Blob) {
// 构造响应,自动渲染
const file = new File([blob], name, { });
this.hidden = true;
this.handleChange({ target: { files: [file] } });
}
});
}
},
methods: {
async handleChange(e) {
this.loading = true;
try {
const [file] = e.target.files;
const arrayBuffer = await readBuffer(file);
this.loading = false;
this.last = await this.displayResult(arrayBuffer, file);
} catch (e) {
console.error(e);
} finally {
this.loading = false;
}
},
displayResult(buffer, file) {
// 取得文件名
const { name } = file;
// 取得扩展名
const extend = getExtend(name);
// 输出目的地
const { output } = this.$refs;
// 生成新的dom
const node = document.createElement("div");
// 添加孩子,防止vue实例替换dom元素
if (this.last) {
output.removeChild(this.last.$el);
this.last.$destroy();
}
const child = output.appendChild(node);
// 调用渲染方法进行渲染
return new Promise((resolve, reject) =>
render(buffer, extend, child).then(resolve).catch(reject)
);
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.banner {
overflow: auto;
text-align: center;
/* background-color: #12b6ff; */
color: #000;
}
.hidden .banner {
display: none;
}
.hidden .well {
height: calc(100vh - 12px);
}
.file-select {
position: absolute;
left: 5%;
top: 17px;
margin-left: 20px;
}
.banner div {
color: #000;
}
.banner h1 {
font-size: 20px;
line-height: 2;
margin: 0.5em 0;
}
.well {
display: block;
background-color: #f2f2f2;
border: 1px solid #ccc;
margin: 5px;
width: calc(100% - 12px);
height: calc(100vh - 73px);
overflow: auto;
}
.loading {
text-align: center;
padding-top: 50px;
}
.messages .warning {
color: #cc6600;
}
</style>
<style>
.pptx-wrapper {
max-width: 1000px;
margin: 0 auto;
}
</style>
2.通过上传获取文件arrayBuffer和Url方式(都转换成html 和css方式)
具体效果可以参考: https://viewer.flyfish.group/
代码地址:https://git.flyfish.dev/flyfish-group/file-viewer-demo
如果要获取最新的源码,要找人家开放私库权限(文章链接里面有)
参考文章链接: https://blog.csdn.net/wybaby168/article/details/122842866?spm=1001.2014.3001.5502
//对应解析的插件
word预览是用的docxjs
pdf预览是用的pdfjs
ppt预览是用的pptx2html
// 主要代码
<template>
<div class="file-viewer">code>
<div class="name">{ -- -->{ filename}}</div>code>
<div v-if="error" class="content loading">{ -- -->{ error}}</div>code>
<template v-else>
<div v-show="loading" class="content loading">{ -- -->{ message}}</div>code>
<div v-show="!loading" class="content" ref="output"></div>code>
</template>
</div>
</template>
<script>
import { -- --> getExtend, render } from "./util";
import axios from "axios";
import { readBuffer } from "../../common/util";
const messages = {
loading: '正在加载中,请耐心等待...',
reading: '正在努力解析文件...',
errorLoading: e => `加载文件异常:${ e}`,
errorReading: e => `读取文件异常:${ e}`,
}
export default {
name: "FileViewer",
props: {
file: {
type: [File, Blob, ArrayBuffer],
description: '通过文件对象或二进制数据加载文档'
},
url: {
type: String,
description: '通过url加载文档'
}
},
data() {
return {
// 加载状态跟踪
loading: false,
// 存在错误时有值
error: '',
// 消息
message: '',
// 文件名
filename: '',
}
},
watch: {
// url改变时,重新请求
url() {
this.loadFromUrl();
},
file(file) {
this.resolveFile(file);
},
},
mounted() {
if (this.file) {
this.resolveFile(this.file);
}
this.loadFromUrl();
},
methods: {
// 从url加载
async loadFromUrl() {
// 要预览的文件地址
const { url } = this;
if (!url) return;
this.startLoading(messages.loading)
const filename = url.substr(url.lastIndexOf('/') + 1);
// 拼接ajax请求文件内容
try {
const { data } = await axios({ url, method: 'get', responseType: 'blob' });
// 展示错误
if (!data) return this.showError('文件下载失败');
// 手动构建一个file
const file = this.wrap(data, filename);
// 解析文件
return this.resolveFile(file);
} catch (e) {
this.showError(messages.errorLoading(e));
} finally {
this.endLoading();
}
},
// 包装file
wrap(data, filename) {
if (data instanceof File) {
return data;
}
if (data instanceof Blob) {
return new File([ data ], filename, { });
}
if (data instanceof ArrayBuffer) {
return this.wrap(new Blob([ data ]));
}
},
// 处理并解析文件
async resolveFile(data) {
// 停止之前的加载
if (this.loading) this.endLoading();
// 安全的包装文件
const file = this.wrap(data);
// 开始加载
this.startLoading(messages.reading);
try {
this.filename = file.name && decodeURIComponent(file.name) || '';
const arrayBuffer = await readBuffer(file);
this.last = await this.displayResult(arrayBuffer, file)
} catch (e) {
this.showError(messages.errorReading(e));
} finally {
this.endLoading();
}
},
// 展示渲染最终效果
displayResult(buffer, file) {
// 取得文件名
const { name } = file;
// 取得扩展名
const extend = getExtend(name);
// 输出目的地
const { output } = this.$refs;
// 生成新的dom
const node = document.createElement('div');
// 添加孩子,防止vue实例替换dom元素
if (this.last) {
output.removeChild(output.lastChild);
this.last.$destroy();
}
const child = output.appendChild(node);
// 调用渲染方法进行渲染
return new Promise((resolve, reject) => render(buffer, extend, child)
.then(resolve).catch(reject));
},
showError(message) {
this.error = message;
},
startLoading(message) {
this.loading = true;
this.message = message;
this.error = '';
},
endLoading() {
this.loading = false;
this.message = '';
}
}
}
</script>
<style scoped>
.file-viewer {
position: relative;
}
.content {
display: block;
background-color: #f2f2f2;
border: 1px solid #ccc;
margin: 5px;
width: calc(100% - 12px);
height: calc(100vh - 73px);
overflow: auto;
}
.loading {
text-align: center;
padding-top: 50px;
}
.name {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 13px 0;
font-size: 20px;
text-shadow: 2px 2px #616161;
pointer-events: none;
color: white;
background: rgba(31, 31, 31, 0.22);
text-align: center;
z-index: 10000;
}
</style>
四、vue-pdf插件
arrayBuffer和Url方式都支持
npm install --save vue-pdf
import pdf from 'vue-pdf'
1.全文预览
<template>
<div>
<pdf
v-for="i in numPages"code>
:key="i"code>
:page="i"code>
:src="pdfUrl"code>
style="width: 100%"code>
@num-pages="pageCount = $event"code>
></pdf>
</div>
</template>
<script>
import pdf from 'vue-pdf';
export default { -- -->
name: 'PDF',
components: { pdf },
data() {
return {
pageCount: 10, //当前页
pdfUrl: '',
src: 'https://.pdf', // pdf文件地址
numPages: 0, //总页数
};
},
mounted() {
this.loadPdfHandler();
},
methods: {
async loadPdfHandler() {
this.pdfUrl = pdf.createLoadingTask(this.src);
this.pdfUrl.promise.then(pdf => {
this.numPages = pdf.numPages;
});
},
},
};
</script>
2.指定页数,直接预览到某页的
<template>
<div class="pdf-preview-out" v-loading="boxLoading">code>
<!-- 上部 外层容器 用于滚动-->
<div class="scroll-box">code>
<!-- 用于截取调缩放后的空白区域 -->
<div class="pdf-box">code>
<!-- pdf预览区域(会被缩放) -->
<div :style="getPdfSize()" class="pdf-scale-box">code>
<!-- 预览组件 -->
<pdf
:src="url"code>
:page="currentPage"code>
@num-pages="getTotalPage"code>
@page-loaded="pageLoaded"code>
@loaded="mountedLoaded"code>
></pdf>
</div>
</div>
</div>
<!-- 底部操作栏 -->
<div class="bottom-tools">code>
<div>共 { -- -->{ pageTotal }} 页</div>
<div class="page">code>
<el-button round type="primary" :disabled="currentPage === 1" @click="chengPage">code>
上一页
</el-button>
<!-- 页码展示及跳转 -->
<el-button
round
type="primary"code>
:disabled="currentPage === pageTotal"code>
@click="chengPage('+')"code>
>
下一页
</el-button>
</div>
<div class="scale">code>
<el-button
type="primary"code>
icon="el-icon-minus"code>
circle
:disabled="pageScale - 0.1 < 0.3"code>
@click="scalePage"code>
></el-button>
<el-button
type="primary"code>
icon="el-icon-plus"code>
circle
:disabled="pageScale + 0.1 > 1"code>
@click="scalePage('+')"code>
></el-button>
</div>
</div>
</div>
</template>
<script>
// 插件引入
import pdf from 'vue-pdf';
export default { -- -->
components: {
pdf,
},
data() {
return {
// 总页数
pageTotal: 0,
// 当前页
currentPage: 3,
// 缩放比例
pageScale: 0.8,
// 遮罩
boxLoading: true,
pageChangeTimer: null,
url: 'https://.pdf',
};
},
methods: {
// 获取到pdf总页数时触发 会传入总页数
getTotalPage(page) {
this.pageTotal = page;
},
// 初始化加载完毕触发
mountedLoaded() {
// 去除遮罩
this.boxLoading = false;
},
// 每加载完成一页时触发(初始化/翻页时均会触发)
pageLoaded() {
// 重新设置pdf预览区域容器外容器的尺寸
this.setPdfBoxSize();
},
// 设置pdf预览区域容器的缩放尺寸
getPdfSize() {
return {
transform: `scale(${ this.pageScale})`,
};
},
// 点击缩放时触发
scalePage(type) {
// 改变缩放比例
let sacle = 0;
if (type === '+') {
sacle = this.pageScale + 0.1;
} else {
sacle = this.pageScale - 0.1;
}
// 可能会涉及js的精度损失 保留一位小数即可
this.pageScale = Number(sacle.toFixed(1));
// 缩放后pdf预览区域容器中会有留白 重新设置pdf预览区域容器外容器的尺寸
this.setPdfBoxSize();
},
// 方法 翻页
chengPage(type) {
// 防抖 0.5秒内不再次触发时执行
if (this.pageChangeTimer) {
clearTimeout(this.pageChangeTimer);
}
// 执行翻页
this.pageChangeTimer = setTimeout(() => {
if (type === '+') {
this.currentPage += 1;
} else {
this.currentPage -= 1;
}
// 翻页后将滚动条归位到顶部
this.scrollbarReset();
this.pageChangeTimer = null;
}, 500);
},
// 方法 滚动条归位到顶部
scrollbarReset() {
let boxDom = document.querySelector('.scroll-box');
boxDom.scrollTop = 0;
},
// 方法 设置pdf预览区域容器外容器的尺寸
setPdfBoxSize() {
// 缩放后 pdf的显示上会缩小 但元素的实际占地尺寸不会变化(仍是原尺寸) 导致可能会出现部分区域留白 通过改变pdf预览区域容器外容器的尺寸 来将留白区域hidden
// 获取pdf的原尺寸
let boxDom = document.querySelector('.pdf-scale-box');
// 获取要设置尺寸的元素dom
let setDom = document.querySelector('.pdf-box');
// 如有缩放 高度根据缩放比例变化(48px是预留的上下外边距)
if (this.pageScale !== 1 && boxDom && setDom) {
setDom.style.height = `${ boxDom.clientHeight * this.pageScale + 48}px`;
} else {
setDom.style.height = '';
}
// console.log(this.pageScale)
// console.log(boxDom.clientWidth * this.pageScale)
},
},
};
</script>
<style lang="scss" scoped>code>
.pdf-preview-out { -- -->
// 高度为占满父组件中的外层容器(若不需要在父组件中设置高度 也可以在本组件中直接设置为所需值)
height: 100%;
// border: 1px solid #909;
&,
div {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
// 滚动容器
.scroll-box {
// 高度按比例 溢出滚动
height: 800px;
overflow: auto;
border: 2px solid #c0d8f3;
border-bottom: none;
border-radius: 6px;
background-color: #eeeeee;
// 滚动条样式
&::-webkit-scrollbar {
width: 10px;
}
&::-webkit-scrollbar-thumb {
background-color: #c0d8f3;
border-radius: 6px;
}
&::-webkit-scrollbar-track {
background-color: transparent;
border-radius: 6px;
}
// 用于缩放后截取掉不需要的空白的容器
.pdf-box {
overflow: hidden;
padding: 24px;
// border: 1px solid rgb(165, 11, 236);
}
// pdf预览区容器
.pdf-scale-box {
box-shadow: 0px 0px 20px 5px #666565;
// border: 2px solid #090;
// 设置缩放的中心点
transform-origin: center top;
transition: 0.2s;
}
}
.bottom-tools {
height: 50px;
line-height: 50px;
background-color: #c0d8f3;
border: 1px solid #5caaf8;
border-radius: 6px;
display: flex;
padding: 0px 24px;
.page {
color: #636a70;
flex-grow: 1;
// border: 1px solid #909;
span {
margin-right: 20px;
}
}
.scale {
// border: 1px solid #909;
text-align: right;
}
}
}
</style>
链接: https://blog.csdn.net/m0_71537867/article/details/131614868
五、pptx.js插件
另外预览ppt还有一个插件pptx但是我没试,放两个链接,你们可以自己试试
链接: https://www.cnblogs.com/xyulz/p/17812301.html
链接: https://blog.51cto.com/u_16213605/8386577
重要写完了~~~~~心累
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。