全国免费咨询:

13245491521

VR图标白色 VR图标黑色
X

中高端软件定制开发服务商

与我们取得联系

13245491521     13245491521

2024-05-14_前端实现文件预览img、docx、xlsx、ppt、pdf、md、txt、audio、video

您的位置:首页 >> 新闻 >> 行业资讯

前端实现文件预览img、docx、xlsx、ppt、pdf、md、txt、audio、video 点击关注公众号,“技术干货”及时达! 前言?最近有接到一个需求,要求前端支持上传制定后缀文件,且支持页面预览,上传简单,那么预览该怎么实现呢,尤其是不同类型的文件预览方案,那么下面就我这个需求的实现,答案在下面 ??: ?「具体的预览需求:」预览需要支持的文件类型有: png、jpg、jpeg、docx、xlsx、ppt、pdf、md、txt、audio、video,另外对于不同文档还需要有定位的功能。例如:pdf 定位到页码,txt和markdown定位到文字并滚动到指定的位置,音视频定位到具体的时间等等。 「?? 补充: 我的需求是需要先将文件上传到后台,所以我拿到的是url地址去展示,对于markdown和txt的文件需要先用fetch获取,其他的展示则直接使用url链接就可以。」不同文件的实现方式不同,下面分类讲解,总共分为以下几类: 自有标签文件:png、jpg、jpeg、audio、video纯文字的文件: markdown & txtoffice 类型的文件: docx、xlsx、pptembed 引入文件:pdfiframe:引入外部完整的网站自有标签文件:png、jpg、jpeg、audio、video?对于图片、音视频的预览,直接使用对应的标签即可,如下: ?图片:png、jpg、jpeg「示例代码:」 img src={url} key={docId} alt={name} width="100%" / 「预览效果如下:」 音频:audio「示例代码:」 audio ref={audioRef} controls controlsList="nodownload" style={{ width: '100%' }} track kind="captions" / source src={url} type="audio/mpeg" / /audio 「预览效果如下:」 视频:video「示例代码:」 video ref={videoRef} controls muted controlsList="nodownload" style={{ width: '100%' }} track kind="captions" / source src={url} type="video/mp4" / /video 「预览效果如下:」 「关于音视频的定位的完整代码:」 import React, { useRef, useEffect } from 'react'; interface IProps { type: 'audio' | 'video'; url: string; timeInSeconds: number; } function AudioAndVideo(props: IProps) { const { type, url, timeInSeconds } = props; const videoRef = useRefHTMLVideoElement(null); const audioRef = useRefHTMLAudioElement(null); useEffect(() = { // 音视频定位 const secondsTime = timeInSeconds / 1000; if (type === 'audio' && audioRef.current) { audioRef.current.currentTime = secondsTime; } if (type === 'video' && videoRef.current) { videoRef.current.currentTime = secondsTime; } }, [type, timeInSeconds]); return ( div {type === 'audio' ? ( audio ref={audioRef} controls controlsList="nodownload" style={{ width: '100%' }} track kind="captions" / source src={url} type="audio/mpeg" / /audio ) : ( video ref={videoRef} controls muted controlsList="nodownload" style={{ width: '100%' }} track kind="captions" / source src={url} type="video/mp4" / /video )} /div ); } export default AudioAndVideo; 纯文字的文件: markdown & txt?对于markdown、txt类型的文件,如果拿到的是文件的url的话,则无法直接显示,需要请求到内容,再进行展示。 ?markdown 文件?在展示markdown文件时,需要满足字体高亮、代码高亮、如果有字体高亮,需要滚动到字体所在位置、如果有外部链接,需要新开tab页面再打开。 ?需要引入两个库: marked:它的作用是将markdown文本转换(解析)为HTML。 highlight: 它允许开发者在网页上高亮显示代码。 「字体高亮的代码实现:」 ?高亮的样式,可以在行间样式定义 ? const highlightAndMarkFirst = (text: string, highlightText: string) = { let firstMatchDone = false; const regex = new RegExp(`(${highlightText})`, 'gi'); return text.replace(regex, (match) = { if (!firstMatchDone) { firstMatchDone = true; return `span id='first-match' style="color: red;"${match}/span } return `span style="color: red;"${match}/span }); }; 「代码高亮的代码实现:」 ?需要借助hljs这个库进行转换 ?marked.use({ renderer: { code(code, infostring) { const validLang = !!(infostring && hljs.getLanguage(infostring)); const highlighted = validLang ? hljs.highlight(code, { language: infostring, ignoreIllegals: true }).value : code; return `precode class="hljs ${infostring}"${highlighted}/code/pre } }, }); 「链接跳转新tab页的代码实现:」 marked.use({ renderer: { // 链接跳转 link(href, title, text) { const isExternal = !href.startsWith('/') && !href.startsWith('#'); if (isExternal) { return `a href="${href}" title="${title}" target="_blank" rel="noopener noreferrer"${text}`; } return `a href="${href}" title="${title}"${text}`; }, }, }); 「滚动到高亮的位置的代码实现:」 ?需要配合上面的代码高亮的方法 ?const firstMatchElement = document.getElementById('first-match'); if (firstMatchElement) { firstMatchElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); } 「完整的代码如下:」 ?入参的docUrl 是markdown文件的线上url地址,searchText 是需要高亮的内容。 ?import React, { useEffect, useState, useRef } from 'react'; import { marked } from 'marked'; import hljs from 'highlight.js'; const preStyle = { width: '100%', maxHeight: '64vh', minHeight: '64vh', overflow: 'auto', }; // Markdown展示组件 function MarkdownViewer({ docUrl, searchText }: { docUrl: string; searchText: string }) { const [markdown, setMarkdown] = useState(''); const markdownRef = useRefHTMLDivElement | null(null); const highlightAndMarkFirst = (text: string, highlightText: string) = { let firstMatchDone = false; const regex = new RegExp(`(${highlightText})`, 'gi'); return text.replace(regex, (match) = { if (!firstMatchDone) { firstMatchDone = true; return `span id='first-match' style="color: red;"${match}/span } return `span style="color: red;"${match}/span }); }; useEffect(() = { // 如果没有搜索内容,直接加载原始Markdown文本 fetch(docUrl) .then((response) = response.text()) .then((text) = { const highlightedText = searchText ? highlightAndMarkFirst(text, searchText) : text; setMarkdown(highlightedText); }) .catch((error) = console.error('加载Markdown文件失败:', error)); }, [searchText, docUrl]); useEffect(() = { if (markdownRef.current) { // 支持代码高亮 marked.use({ renderer: { code(code, infostring) { const validLang = !!(infostring && hljs.getLanguage(infostring)); const highlighted = validLang ? hljs.highlight(code, { language: infostring, ignoreIllegals: true }).value : code; return `precode class="hljs ${infostring}"${highlighted}/code/pre }, // 链接跳转 link(href, title, text) { const isExternal = !href.startsWith('/') && !href.startsWith('#'); if (isExternal) { return `a href="${href}" title="${title}" target="_blank" rel="noopener noreferrer"${text}`; } return `a href="${href}" title="${title}"${text}`; }, }, }); const htmlContent = marked.parse(markdown); markdownRef.current!.innerHTML = htmlContent as string; // 当markdown更新后,检查是否需要滚动到高亮位置 const firstMatchElement = document.getElementById('first-match'); if (firstMatchElement) { firstMatchElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); } } }, [markdown]); return ( div style={preStyle} div ref={markdownRef} / /div ); } export default MarkdownViewer; 「预览效果如下:」 txt 文件预览展示?支持高亮和滚动到指定位置 ?「支持高亮的代码:」 function highlightText(text: string) { if (!searchText.trim()) return text; const regex = new RegExp(`(${searchText})`, 'gi'); return text.replace(regex, `span style="color: red"/span } 「完整代码:」 import React, { useEffect, useState, useRef } from 'react'; import { preStyle } from './config'; function TextFileViewer({ docurl, searchText }: { docurl: string; searchText: string }) { const [paragraphs, setParagraphs] = useStatestring[] const targetRef = useRefHTMLDivElement | null(null); function highlightText(text: string) { if (!searchText.trim()) return text; const regex = new RegExp(`(${searchText})`, 'gi'); return text.replace(regex, `span style="color: red"/span } useEffect(() = { fetch(docurl) .then((response) = response.text()) .then((text) = { const highlightedText = highlightText(text); const paras = highlightedText .split('\n') .map((para) = para.trim()) .filter((para) = para); setParagraphs(paras); }) .catch((error) = { console.error('加载文本文件出错:', error); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [docurl, searchText]); useEffect(() = { // 处理高亮段落的滚动逻辑 const timer = setTimeout(() = { if (targetRef.current) { targetRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' }); } }, 100); return () = clearTimeout(timer); }, [paragraphs]); return ( div style={preStyle} {paragraphs.map((para: string, index: number) = { const paraKey = para + index; // 确定这个段落是否包含高亮文本 const isTarget = para.includes(`${searchText} return ( p key={paraKey} ref={isTarget && !targetRef.current ? targetRef : null} div dangerouslySetInnerHTML={{ __html: para }} / ); })} /div ); } export default TextFileViewer; 「预览效果如下:」 office 类型的文件: docx、xlsx、ppt?docx、xlsx、ppt 文件的预览,用的是office的线上预览链接 + 我们文件的线上url即可。 ??关于定位:用这种方法我暂时尝试是无法定位页码的,所以定位的功能我采取的是后端将office 文件转成pdf,再进行定位,如果只是纯展示,忽略这个问题即可。 ?「示例代码:」 iframe src={`https://view.officeapps.live.com/op/view.aspx?src=${url}`} width="100%" height="500px" frameBorder="0" /iframe 「预览效果如下:」 embed 引入文件:pdf?在pdf文档预览时,可以采用embed的方式,这个httpsUrl就是你的pdf文档的链接地址 ?「示例代码:」 embed src={`${httpsUrl}`} style={preStyle} key={`${httpsUrl}`} / 关于定位,其实是地址上拼接的页码sourcePage,如下: const httpsUrl = sourcePage ? `${doc.url}#page=${sourcePage}` : doc.url; embed src={`${httpsUrl}`} style={preStyle} key={`${httpsUrl}`} / 「预览效果如下:」 iframe:引入外部完整的网站?除了上面的各种文件,我们还需要预览一些外部的网址,那就要用到iframe的方式 ?「示例代码:」 iframe title="网址" width="100%" height="100%" src={doc.url} allow="microphone;camera;midi;encrypted-media;"/ 「预览效果如下:」 总结: 到这里我们支持的所有文件都讲述完了,有什么问题,欢迎评论区留言! 点击关注公众号,“技术干货”及时达! 阅读原文

上一篇:2024-01-04_七张图解锁Mybatis整体脉络,让你轻松拿捏面试官 下一篇:2022-11-16_奖项vs销量 , 广告人再次遭“吐槽“

TAG标签:

17
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设网站改版域名注册主机空间手机网站建设网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。
项目经理在线

相关阅读 更多>>

猜您喜欢更多>>

我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!

不达标就退款

高性价比建站

免费网站代备案

1对1原创设计服务

7×24小时售后支持

 

全国免费咨询:

13245491521

业务咨询:13245491521 / 13245491521

节假值班:13245491521()

联系地址:

Copyright © 2019-2025      ICP备案:沪ICP备19027192号-6 法律顾问:律师XXX支持

在线
客服

技术在线服务时间:9:00-20:00

在网站开发,您对接的直接是技术员,而非客服传话!

电话
咨询

13245491521
7*24小时客服热线

13245491521
项目经理手机

微信
咨询

加微信获取报价