1.引入查看的封装的组件
<template>
<div>
<div class="well" ref="output"></div>
</div>
</template>
<script>
import { getExtend, readBuffer, render } from './util';
/**
* 支持嵌入式显示,基于postMessage支持跨域
* 示例代码:
*
*/
export default {
name: "openFile",
props: {
file: {
type: File
}
},
data() {
return {
// 上个渲染实例
last: null
};
},
mounted() {
console.log(222)
this.handleChange({ target: { files: [this.file] } });
},
methods: {
async handleChange(e) {
console.log(11111)
try {
const [file] = e.target.files;
const arrayBuffer = await readBuffer(file);
this.last = await this.displayResult(arrayBuffer, file);
console.log(this.last)
} catch (e) {
console.error(e);
}
},
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);
display: flex;
justify-content: center;
align-items: center;
}
.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.renders.js 分类
import { defaultOptions, renderAsync } from "docx-preview";
import renderPptx from "./vendors/pptx";
import renderSheet from "./vendors/xlsx";
import renderPdf from "./vendors/pdf";
import renderImage from "./vendors/image";
import renderText from "./vendors/text";
import renderMp4 from "./vendors/mp4";
// 假装构造一个vue的包装,让上层统一处理销毁和替换节点
const VueWrapper = (el) => ({
$el: el,
$destroy() {
// 什么也不需要 nothing to do
},
});
const handlers = [
// 使用docxjs支持,目前效果最好的渲染器
{
accepts: ["docx"],
handler: async (buffer, target) => {
const docxOptions = Object.assign(defaultOptions, {
debug: true,
experimental: true,
});
await renderAsync(buffer, target, null, docxOptions);
return VueWrapper(target);
},
},
// 使用pptx2html,已通过默认值更替
{
accepts: ["pptx"],
handler: async (buffer, target) => {
await renderPptx(buffer, target, null);
window.dispatchEvent(new Event("resize"));
return VueWrapper(target);
},
},
// 使用sheetjs + handsontable,无样式
{
accepts: ["xlsx"],
handler: async (buffer, target) => {
return renderSheet(buffer, target);
},
},
// 使用pdfjs,渲染pdf,效果最好
{
accepts: ["pdf"],
handler: async (buffer, target) => {
return renderPdf(buffer, target);
},
},
// 图片过滤器
{
accepts: ["gif", "jpg", "jpeg", "bmp", "tiff", "tif", "png", "svg"],
handler: async (buffer, target) => {
return renderImage(buffer, target);
},
},
// 纯文本预览
{
accepts: [
"txt",
"json",
"js",
"css",
"java",
"py",
"html",
"jsx",
"ts",
"tsx",
"xml",
"md",
"log",
],
handler: async (buffer, target) => {
return renderText(buffer, target);
},
},
// 视频预览,仅支持MP4
{
accepts: ["mp4"],
handler: async (buffer, target) => {
renderMp4(buffer, target);
return VueWrapper(target);
},
},
// 错误处理
{
accepts: ["error"],
handler: async (buffer, target, type) => {
target.innerHTML = `<div style="text-align: center; margin-top: 80px">不支持.${type}格式的在线预览,请下载后预览或转换为支持的格式</div>
<div style="text-align: center">支持docx, xlsx, pptx, pdf, 以及纯文本格式和各种图片格式的在线预览</div>`;
return VueWrapper(target);
},
},
];
// 匹配
export default handlers.reduce((result, { accepts, handler }) => {
accepts.forEach((type) => (result[type] = handler));
return result;
}, {});
3.二进制流转文件
const mimeType = {
xls: 'application/xls',
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
doc: ' application/msword',
docx: ' application/vnd.openxmlformats-officedocument.wordprocessingml.document',
ppt: 'application/vnd.ms-powerpoint',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
png: 'image/png ',
jpg: 'image/jpeg ',
jpeg: 'image/jpeg ',
gif: 'image/gif ',
txt: 'text/plain',
mp4: 'video/mp4'
};
const mime = mimeType[suffix] || 'application/octet-stream';
console.log(blob);
const file = new File([blob], row.fileName, { type: mime });
console.log(file);
// file == files[0]
this.file = file;
具体实现