当前位置: 首页 > news >正文

客户端(浏览器)vue3本地预览txt,doc,docx,pptx,pdf,xlsx,csv,

预览文件

  • 1、入口文件preview/index.vue
  • 2、预览txt
  • 3、预览doc
  • 4、预览pdf
  • 5、预览pptx
  • 6、预览xlsx
  • 7、预览csv

1、入口文件preview/index.vue

预览样式,如pdf
在这里插入图片描述

文件目录如图所示:
在这里插入图片描述
代码如下

<template><div class="preview-wrap" ref="previewDom" v-if="hasPreviewFlag"><DocxPreview v-if="fileType === 'docx' || fileType === 'doc'" :file-data="fileData" /><PdfPreview v-else-if="fileType === 'pdf'" :file-data="fileData" /><TxtPreview v-else-if="fileType === 'txt'" :file-data="fileData" /><XlsxPreview v-else-if="fileType === 'xlsx'" :file-data="fileData" /><PptxPreview v-else-if="fileType === 'pptx'" :file-data="fileData" :file-id="row.id"/><CsvPreview v-else-if="fileType === 'csv'" :file-data="fileData" file-type="csv" /><div v-else><el-resulticon="error"title="提示"sub-title="文件不存在或者异常"/></div></div>
</template><script setup>
import { ElMessage } from 'element-plus'
import DocxPreview from './components/DocxPreview.vue'
import PdfPreview from './components/PdfPreview.vue'
import TxtPreview from './components/TxtPreview.vue'
import XlsxPreview from './components/XlsxPreview.vue'
import PptxPreview from './components/PptxPreview.vue'
import CsvPreview from './components/CsvPreview.vue'
import { ref, onMounted, defineProps } from 'vue'const props = defineProps({row: {type: Object,default: () => {},},
})
const filePath = ref('')
const fileType = ref('')
const fileData = ref(null)
const hasPreviewFlag = ref(true)onMounted(() => {// console.log('row', props.row)const typeList = ['docx', 'doc', 'txt', 'pdf', 'xlsx', 'pptx', 'csv'] // 目前支持的类型filePath.value = props.row.cached_file_path || ''filePath.value = 'D:\\work\\test.txt' || props.row // 调试用// filePath.value = 'D:\\work\\test.docx' || props.row// filePath.value = 'D:\\work\\test.xlsx' || props.row// filePath.value = 'D:\\work\\test.csv' || props.row// filePath.value = 'D:\\work\\test.pdf' || props.row// filePath.value = 'D:\\work\\test.pptx'fileType.value = (filePath.value.split('.').pop() || props.row.file_type).toLowerCase()if (!typeList.includes(fileType.value)) {return ElMessage.error('此文件不支持预览')}if (typeList.includes(fileType.value)) {hasPreviewFlag.value = truewindow.electronAPI?.readFileSend(filePath.value) // 通过绝对路径获取文件流信息} else {hasPreviewFlag.value = false}
})
// 这里根据客户端的主进程和渲染进行通过文件的绝对路径获取文件流
window.electronAPI?.readFileReceive((event, data) => {// console.log('arraybuffer---->', data) // 将arraybuffer转换成bolb形式fileData.value = new Blob([data])
})
</script><style lang="scss">
.preview-wrap {height: calc(100vh - 130px);overflow: auto;z-index: 1;position: relative;padding: 8px;background: white;border: 1px solid #ccc;
}::-webkit-scrollbar {width: 0 !important;
}::-webkit-scrollbar {width: 0 !important;height: 0;
}
</style>

preload.js

  // 跨窗口通信方法-读取文件readFileSend: (...args) => ipcRenderer.send("read-file", ...args),readFileReceive: (cb) => ipcRenderer.on('read-file', cb),

main.js

// 通过文件的绝对路径获取文件流
ipcMain.on('read-file', (event, filePath) => {const currentWindow = BrowserWindow.fromWebContents(event.sender)fs.readFile(filePath, (err, res) => {if (err) {console.log('read-file', err)} else { currentWindow && currentWindow.webContents.send('read-file', res)}})
})

2、预览txt

<template><div><pre class="txtViewer">{{ txtContent }}</pre></div>
</template><script setup>
import { ref, watch, toRefs, defineProps } from 'vue'const props = defineProps({fileData: {type: Blob,default: null}
})
const { fileData } = toRefs(props)
const txtContent = ref('')watch(() => fileData.value,(newv, oldv) => {previewFile(newv)}
)
const previewFile = fileData => {const reader = new FileReader();reader.onload = () => {txtContent.value = reader.result;};reader.readAsText(fileData);
}</script><style lang="scss" scoped>
.txtViewer {width: 100%;height: 100%;overflow: auto;margin-bottom: 0;white-space: pre-wrap;
}
</style>

3、预览doc

采用docx-preview

<template><div><div id="docx-content-preview" class="docFile" v-show="!loading"></div></div>
</template><script setup>
import { renderAsync } from 'docx-preview'
import { ref, defineProps, watch, toRefs } from 'vue'const loading = ref(true)
const props = defineProps({fileData: {type: Object,default: () => {},},
})const { fileData } = toRefs(props);watch(() => fileData.value,val => {loading.value = truepreviewfile(val)},{ deep: true }
)
function previewfile(fileData) {// 选择要渲染的元素const docFile = document.getElementsByClassName('docFile')// const blob = new Blob([fileData])// 用docx-preview渲染renderAsync(fileData, docFile[0]).then(res => {console.log('res---->', res)loading.value = false})
}
</script><style lang="scss" scoped>
#docx-content-preview {min-height: 200px;overflow-x: hidden;padding: 10px;
}
.docFile {:deep(.docx-wrapper) {background: white;}:deep(section) {width: 100% !important;box-shadow: none;}
}:deep(.docx-wrapper > section.docx) {width: 100% !important;padding: 0rem !important;min-height: auto !important;box-shadow: none;margin-bottom: 0;article {overflow: auto;}
}
</style>

4、预览pdf

实现的方式有多种,可采用pdfjs-dist、或
pdf.worker.min.mj可在官网上下载

<template><div style="position:relative;"><div style="text-align: center; position: relative" ref="pdfViewer" class="pdfViewer"></div></div>
</template><script setup>
import * as pdfjsLib from 'pdfjs-dist'
import { ref, watch, toRefs } from 'vue'
pdfjsLib.GlobalWorkerOptions.workerSrc = "./pdf.worker.min.mjs";const props = defineProps({fileData: {type: Blob,default: null}
})
const { fileData } = toRefs(props);
const pdfViewer = ref()
const loading = ref(true)
const allParagraphs = ref([])
const canvasHistory = ref({})
// const scale = 1.5
const scale = window.devicePixelRatio > 1.3 ? 1 : 1.5watch(() => fileData.value,async (newVal, oldVal) => {clearRec();previewFile(newVal)},{ deep: true }
)const previewFile = (fileData) => {getUint8ArrayData(fileData).then((uint8Array) => {renderPdf(uint8Array)})
}const getUint8ArrayData = (blob) => {return new Promise((resolve, reject) => {// 使用FileReader读取Blob对象const fileReader = new FileReader()fileReader.onload = function () {// 读取完成后,result属性将包含Uint8Array数据const uint8Array = new Uint8Array(fileReader.result)resolve(uint8Array)}fileReader.onerror = function () {console.error('读取Blob时发生错误')reject(new Error('读取Blob时发生错误'))}// 开始读取BlobfileReader.readAsArrayBuffer(blob)})
}
const renderPdf = async (uint8Array) => {const loadingTask = pdfjsLib.getDocument(uint8Array)const pdf = await loadingTask.promisefor (let i = 1; i <= pdf.numPages; i++) {await renderPage(pdf, i)}loading.value = false;
}const renderPage = async (pdf, pageNumber) => {// 构造canvasconst canvas = document.createElement('canvas')canvas.style = 'direction: ltr;position: relative'canvas.id = `canvas_page_${pageNumber}`canvas.className = `canvas_page`// 构造文本层const layerDiv = document.createElement('div')layerDiv.style ='position: absolute;left: 0;top: 0;right: 0;bottom: 0;overflow: hidden;opacity: 0.4;line-height: 1.0;'layerDiv.id = `canvas_layer_page_${pageNumber}`layerDiv.className = 'canvas-layer'const div = document.createElement('div')div.style = 'width: fit-content;margin: 0 auto;position:relative; border: 1px solid #ccc; margin-bottom: 8px;'div.id = `page-container-${pageNumber}`div.className = `page-container`div.appendChild(canvas)// div.appendChild(layerDiv)pdfViewer.value.appendChild(div)const page = await pdf.getPage(pageNumber)const viewport = page.getViewport({ scale })// Support HiDPI-screens.const outputScale = window.devicePixelRatio || 1// Prepare canvas using PDF page dimensionsconst context = canvas.getContext('2d')canvas.width = Math.floor(viewport.width * outputScale)canvas.height = Math.floor(viewport.height * outputScale)canvas.style.width = Math.floor(viewport.width) + 'px'canvas.style.height = Math.floor(viewport.height) + 'px'canvas.style.maxWidth = 1200 + 'px'  // 解决pdf文档宽度过长导致样式错乱const transform =outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null// Render PDF page into canvas contextconst renderContext = {canvasContext: context,transform,viewport,}await page.render(renderContext).promise// 存入画布渲染pdf的状态,用于还原canvasHistory.value[pageNumber] = canvas.toDataURL()const textContent = await page.getTextContent()// Pass the data to the method for rendering of text over the pdf canvas.// const task = pdfjsLib.renderTextLayer({//   textContentSource: page.streamTextContent(),//   container: layerDiv,//   viewport,//   textDivs: [],// })// await task.promise// 处理得到每页的paragraphconst pageParagraphs = handleParagraphs(pageNumber,canvas,viewport,textContent.items)await clearRec()allParagraphs.value = allParagraphs.value.concat(pageParagraphs)
}const handleParagraphs = (pageNumber, canvas, viewport, textContent) => {const newArr = groupByTransform(pageNumber,(textContent || []).filter((item) => !!item.str.trim()))const paragraphs = newArr.map((item) => {return {pageNumber,canvas,viewport,content: item.map((it) => it.str).reduce((a, b) => {return a + b}, ''),items: item,}})return paragraphs
}
const groupByTransform = (pageNumber, array) => {const result = []const map = new Map()array.forEach((obj) => {const key = obj.transform[5]if (!map.has(key)) {map.set(key, [obj])} else {map.get(key).push(obj)}})map.forEach((value) => {result.push(value)})return result
}
const clearRec = async () => {for (const key in canvasHistory.value) {const canvas = document.getElementById(`canvas_page_${key}`)if (canvas) {const context = canvas.getContext("2d");const canvasPic = await loadPdfImage(key)context.drawImage(canvasPic, 0, 0);} else {console.log('获取节点失败', `canvas_page_${key}`)}}
}const loadPdfImage = (index) => {return new Promise((resolve, reject) => {const canvasPic = new Image();canvasPic.src = canvasHistory.value[index]canvasPic.onload = () => {// 当图像加载完成后进行resolve,确保drawImage执行成功resolve(canvasPic)}canvasPic.onerror = () => {reject(new Error('加载还原图像失败'))}})
}
</script><style lang="scss" scoped>
.pdfViewer {min-height: 100%;:deep(.canvas-layer > span) {color: transparent;position: absolute;white-space: pre;cursor: text;transform-origin: 0% 0%;background: transparent;z-index: 1;}:deep(.page-container) {width: 100% !important;.canvas_page {width: 100% !important;height: 100% !important;}}
}
</style>

5、预览pptx

6、预览xlsx

7、预览csv

相关文章:

客户端(浏览器)vue3本地预览txt,doc,docx,pptx,pdf,xlsx,csv,

预览文件 1、入口文件preview/index.vue2、预览txt3、预览doc4、预览pdf5、预览pptx6、预览xlsx7、预览csv 1、入口文件preview/index.vue 预览样式&#xff0c;如pdf 文件目录如图所示&#xff1a; 代码如下 <template><div class"preview-wrap" ref&…...

[SZ901]JTAG高速下载设置(53Mhz)

SZ901最高支持JTAG 53MHz的时钟频率&#xff0c;下载bit文件和固化程序的速度提升非常明显。 首先设置参数 1&#xff0c;将JTAG0 分频系数修改为3 2&#xff0c;设置参数&#xff0c;更新参数。&#xff08;完成&#xff09; 打开VIVADO VIVADO 正常识别FPGA&#xff0c;速…...

docker springboot 运维部署详细实例

环境安装 [rootiZbp1dcnzq7pzpg9607m6pZ ~]# docker -v Docker version 26.1.4, build 5650f9b镜像构建 Dockerfile 文件内容 FROM openjdk:8 # Author Info 创建人信息 MAINTAINER ratelcloudfoxmail.com ENV PORT20001 EXPOSE 20001 RUN mkdir /usr/local/ratel-boot-serv…...

Linux 查看目录命令 ls 详细介绍

Linux 和 Unix 系统中 ls 命令是用于列出目录内容。用户可以查看指定目录下的文件和子目录&#xff0c;还可以获取有关这些文件和子目录的详细信息。 基本语法&#xff1a; ls [选项] [目录]如果不指定目录&#xff0c;ls 将列出当前工作目录下的内容。 01、-a 或 --all ls…...

React Native状态管理器Redux、MobX、Context API、useState

Redux、MobX、Context API、useState都是React中用于状态管理的工具&#xff0c;但它们各自有不同的特点和使用场景。 Redux 介绍&#xff1a; Redux是一个JavaScript状态管理库&#xff0c;最初由Dan Abramov和Andrew Clark于2015年开发。它基于Flux架构&#xff0c;强调状态…...

Three.js资源-模型下载网站

在使用 Three.js 进行 3D 开发时&#xff0c;拥有丰富的模型资源库可以大大提升开发效率和作品质量。以下是一些推荐的 Three.js 模型下载网站&#xff0c;它们提供了各种类型的 3D 模型&#xff0c;适合不同项目需求。无论你是需要逼真的建筑模型&#xff0c;还是简单的几何体…...

linux 添加默认网关

在linux 可以使用 route 命令添加默认网关&#xff0c;假设添加的默认网关是192.168.159.2 添加方式如下&#xff1a; route add default gw 192.168.159.2 以上命令只需要把add 改成 del &#xff0c;就能删除刚才添加的路由 route del default gw 192.168.159.2 #该命…...

【学习笔记】深入浅出详解Pytorch中的View, reshape, unfold,flatten等方法。

文章目录 一、写在前面二、Reshape&#xff08;一&#xff09;用法&#xff08;二&#xff09;代码展示 三、Unfold&#xff08;一&#xff09;torch.unfold 的基本概念&#xff08;二&#xff09;torch.unfold 的工作原理&#xff08;三&#xff09; 示例代码&#xff08;四&a…...

CTFHUB-web(SSRF)

内网访问 点击进入环境&#xff0c;输入 http://127.0.0.1/flag.php 伪协议读取文件 /?urlfile:///var/www/html/flag.php 右击查看页面源代码 端口扫描 1.根据题目提示我们知道端口号在8000-9000之间,使用bp抓包并进行爆破 POST请求 点击环境&#xff0c;访问flag.php 查看页…...

分解质因数

给定 n个正整数 &#xff0c;将每个数分解质因数&#xff0c;并按照质因数从小到大的顺序输出每个质因数的底数和指数。 输入格式 第一行包含整数 n 接下来 n行&#xff0c;每行包含一个正整数 。 输出格式 对于每个正整数 &#xff0c;按照从小到大的顺序输出其分解质因数后&…...

前景物体提取

参考&#xff1a;精选课&#xff1a;C完整的实现双目摄像头图像采集、双目摄像头畸变矫正、前景物体提取、生成视差图、深度图、PCL点云图 前景物体提取是计算机视觉中的一个重要技术&#xff0c;可以用于视频监控、虚拟现实和计算机视觉等领域。 1.前景物体提取的原理 前景…...

Kotlin复习

一、Kotlin类型 1.整数 2.浮点 显示转换&#xff1a; 所有数字类型都支持转换为其他类型&#xff0c;但是转换前会检测长度。 toByte(): Byte toShort(): Short toInt(): Int toLong(): Long toFloat(): Float toDouble(): Double 不同进制的数字表示方法&#xff08;为了提高…...

【AI日记】24.12.17 kaggle 比赛 2-6 | 把做饭看成一种游戏 | 咖喱牛肉

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 参加&#xff1a;kaggle 比赛 Regression with an Insurance Dataset时间&#xff1a;9 小时睡得好很重要 读书 书名&#xff1a;富兰克林自传时间&#xff1a;0.5 小时阅读原因&#xff1a;100 美元纸…...

操作系统(14)请求分页

前言 操作系统中的请求分页&#xff0c;也称为页式虚拟存储管理&#xff0c;是建立在基本分页基础上&#xff0c;为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能的一种内存管理技术。 一、基本概念 分页&#xff1a;将进程的逻辑地址空间分成若干个大小相等的页&am…...

uniapp navigateTo、redirectTo、reLaunch等页面路由跳转方法的区别

uni.switchTab 跳转到 tabBar 页面&#xff0c;并关闭其他所有非 tabBar 页面 // app.json {"tabBar": {"list": [{"pagePath": "index","text": "首页"},{"pagePath": "other","text&…...

模型 A/B测试(科学验证)

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。控制变量法。 1 A/B测试的应用 1.1 Electronic Arts&#xff08;EA&#xff09;《模拟城市》5游戏网站A/B测试 定义目标&#xff1a; Electronic Arts&#xff08;EA&#xff09;在发布新版《模拟城…...

谷歌发布升级版AI视频生成器Veo 2与图像生成器Imagen 3

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

快速掌握源码部署Filebeat

文章目录 1. 裸金属安装1.1 压缩包方式安装1.2 yum方式安装 2. docker安装3. K8s安装 项目使用了Filebeat&#xff0c;现在需要运行在ARM架构的服务器上&#xff0c;但是Filebeat官方没有提供&#xff0c;需要自己编译一份 filebeat等组件的源码地址 https://github.com/elasti…...

C++ 哈希表封装unordered_map 和 unordered_set

1.源码框架 SGI-STL30版本源代码中没有unordered_map和unordered_set&#xff0c;SGI-STL30版本是C11之前的STL 版本&#xff0c;这两个容器是C11之后才更新的。但是SGI-STL30实现了哈希表&#xff0c;只容器的名字是hash_map 和hash_set&#xff0c;他是作为⾮标准的容器出现…...

pymysql 入门

发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【宝藏入口】。 1. 什么是 PyMySQL&#xff1f; PyMySQL 是一个纯 Python 编写的 MySQL 客户端库&#xff0c;可以通过它轻松地在 Python 中连…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

深入浅出Diffusion模型:从原理到实践的全方位教程

I. 引言&#xff1a;生成式AI的黎明 – Diffusion模型是什么&#xff1f; 近年来&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;领域取得了爆炸性的进展&#xff0c;模型能够根据简单的文本提示创作出逼真的图像、连贯的文本&#xff0c;乃至更多令人惊叹的…...