欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

【W(wǎng)EB 】純JS前端實(shí)現(xiàn)文件預(yù)覽img、docx、xlsx、ppt、pdf、md、txt、audio、video

admin
2024年5月15日 10:55 本文熱度 985

前言

最近有接到一個(gè)需求,要求前端支持上傳制定后綴文件,且支持頁面預(yù)覽,上傳簡(jiǎn)單,那么預(yù)覽該怎么實(shí)現(xiàn)呢,尤其是不同類型的文件預(yù)覽方案,那么下面就我這個(gè)需求的實(shí)現(xiàn),答案在下面 👇:

「具體的預(yù)覽需求:」預(yù)覽需要支持的文件類型有: png、jpg、jpeg、docx、xlsx、ppt、pdf、md、txt、audio、video,另外對(duì)于不同文檔還需要有定位的功能。例如:pdf 定位到頁碼,txtmarkdown定位到文字并滾動(dòng)到指定的位置,音視頻定位到具體的時(shí)間等等。


「⚠️ 補(bǔ)充: 我的需求是需要先將文件上傳到后臺(tái),所以我拿到的是url地址去展示,對(duì)于markdowntxt的文件需要先用fetch獲取,其他的展示則直接使用url鏈接就可以。」

不同文件的實(shí)現(xiàn)方式不同,下面分類講解,總共分為以下幾類:

  1. 自有標(biāo)簽文件:png、jpg、jpeg、audio、video
  2. 純文字的文件: markdown & txt
  3. office 類型的文件: docx、xlsx、ppt
  4. embed 引入文件:pdf
  5. iframe:引入外部完整的網(wǎng)站

自有標(biāo)簽文件:png、jpg、jpeg、audio、video

對(duì)于圖片、音視頻的預(yù)覽,直接使用對(duì)應(yīng)的標(biāo)簽即可,如下:

圖片:png、jpg、jpeg

「示例代碼:」

 <img src={url} key={docId} alt={name} width="100%" />;

「預(yù)覽效果如下:」


音頻:audio

「示例代碼:」

<audio ref={audioRef} controls controlsList="nodownload" style={{ width: '100%' }}>
 <track kind="captions" />
 <source src={url} type="audio/mpeg" />
</audio>

「預(yù)覽效果如下:」


視頻:video

「示例代碼:」

<video ref={videoRef} controls muted controlsList="nodownload" style={{ width: '100%' }}>
 <track kind="captions" />
 <source src={url} type="video/mp4" />
</video>

「預(yù)覽效果如下:」


「關(guān)于音視頻的定位的完整代碼:」

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 = useRef<HTMLVideoElement>(null);
 const audioRef = useRef<HTMLAudioElement>(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

對(duì)于markdown、txt類型的文件,如果拿到的是文件的url的話,則無法直接顯示,需要請(qǐng)求到內(nèi)容,再進(jìn)行展示。

markdown 文件

在展示markdown文件時(shí),需要滿足字體高亮、代碼高亮、如果有字體高亮,需要滾動(dòng)到字體所在位置、如果有外部鏈接,需要新開tab頁面再打開。

需要引入兩個(gè)庫:

marked:它的作用是將markdown文本轉(zhuǎn)換(解析)為HTML

highlight: 它允許開發(fā)者在網(wǎng)頁上高亮顯示代碼。

「字體高亮的代碼實(shí)現(xiàn):」

高亮的樣式,可以在行間樣式定義

  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>`;
   });
 };

「代碼高亮的代碼實(shí)現(xiàn):」

需要借助hljs這個(gè)庫進(jìn)行轉(zhuǎn)換

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 `<pre><code class="hljs ${infostring}">${highlighted}</code></pre>`;
     }
   },
 });

「鏈接跳轉(zhuǎn)新tab頁的代碼實(shí)現(xiàn):」

marked.use({
  renderer: {
     // 鏈接跳轉(zhuǎn)
     link(href, title, text) {
       const isExternal = !href.startsWith('/') && !href.startsWith('#');
       if (isExternal) {
         return `<a href="${href}" title="${title}" target="_blank" rel="noopener noreferrer">${text}</a>`;
       }
       return `<a href="${href}" title="${title}">${text}</a>`;
     },
   },
});

「滾動(dòng)到高亮的位置的代碼實(shí)現(xiàn):」

需要配合上面的代碼高亮的方法

const firstMatchElement = document.getElementById('first-match');
if (firstMatchElement) {
   firstMatchElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
}

「完整的代碼如下:」

入?yún)⒌?code style="margin: 0px 2px; padding: 2px 4px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-radius: 4px; background-color: rgba(27, 31, 35, 0.05); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; word-break: break-all;">docUrl 是markdown文件的線上url地址,searchText 是需要高亮的內(nèi)容。

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 = useRef<HTMLDivElement | 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(() => {
   // 如果沒有搜索內(nèi)容,直接加載原始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 `<pre><code class="hljs ${infostring}">${highlighted}</code></pre>`;
         },
         // 鏈接跳轉(zhuǎn)
         link(href, title, text) {
           const isExternal = !href.startsWith('/') && !href.startsWith('#');
           if (isExternal) {
             return `<a href="${href}" title="${title}" target="_blank" rel="noopener noreferrer">${text}</a>`;
           }
           return `<a href="${href}" title="${title}">${text}</a>`;
         },
       },
     });
     const htmlContent = marked.parse(markdown);
     markdownRef.current!.innerHTML = htmlContent as string;
     // 當(dāng)markdown更新后,檢查是否需要滾動(dòng)到高亮位置
     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;

「預(yù)覽效果如下:」


txt 文件預(yù)覽展示

支持高亮和滾動(dòng)到指定位置

「支持高亮的代碼:」

  function highlightText(text: string) {
   if (!searchText.trim()) return text;
   const regex = new RegExp(`(${searchText})`, 'gi');
   return text.replace(regex, `<span style="color: red">$1</span>`);
 }

「完整代碼:」

import React, { useEffect, useState, useRef } from 'react';
import { preStyle } from './config';

function TextFileViewer({ docurl, searchText }: { docurl: string; searchText: string }) {
 const [paragraphs, setParagraphs] = useState<string[]>([]);
 const targetRef = useRef<HTMLDivElement | 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">$1</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('加載文本文件出錯(cuò):', error);
     });
   // eslint-disable-next-line react-hooks/exhaustive-deps
 }, [docurl, searchText]);

 useEffect(() => {
   //  處理高亮段落的滾動(dòng)邏輯
   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;

       // 確定這個(gè)段落是否包含高亮文本
       const isTarget = para.includes(`>${searchText}<`);
       return (
         <p key={paraKey} ref={isTarget && !targetRef.current ? targetRef : null}>
           <div dangerouslySetInnerHTML={{ __html: para }} />
         </p>
       );
     })}
   </div>
 );
}

export default TextFileViewer;

「預(yù)覽效果如下:」



office 類型的文件: docx、xlsx、ppt

docx、xlsx、ppt 文件的預(yù)覽,用的是office的線上預(yù)覽鏈接 + 我們文件的線上url即可。

關(guān)于定位:用這種方法我暫時(shí)嘗試是無法定位頁碼的,所以定位的功能我采取的是后端將office 文件轉(zhuǎn)成pdf,再進(jìn)行定位,如果只是純展示,忽略這個(gè)問題即可。

「示例代碼:」

<iframe
   src={`https://view.officeapps.live.com/op/view.aspx?src=${url}`}
   width="100%"
   height="500px"
   frameBorder="0"
></iframe>

「預(yù)覽效果如下:」



embed 引入文件:pdf

pdf文檔預(yù)覽時(shí),可以采用embed的方式,這個(gè)httpsUrl就是你的pdf文檔的鏈接地址

「示例代碼:」

 <embed src={`${httpsUrl}`} style={preStyle} key={`${httpsUrl}`} />;

關(guān)于定位,其實(shí)是地址上拼接的頁碼sourcePage,如下:

 const httpsUrl = sourcePage
       ? `${doc.url}#page=${sourcePage}`
       : doc.url;
       
<embed src={`${httpsUrl}`} style={preStyle} key={`${httpsUrl}`} />;    
       

「預(yù)覽效果如下:」



iframe:引入外部完整的網(wǎng)站

除了上面的各種文件,我們還需要預(yù)覽一些外部的網(wǎng)址,那就要用到iframe的方式

「示例代碼:」

 <iframe
   title="網(wǎng)址"
   width="100%"
   height="100%"
   src={doc.url}      
   allow="microphone;camera;midi;encrypted-media;"/>

「預(yù)覽效果如下:」



總結(jié): 到這里我們支持的所有文件都講述完了


該文章在 2024/5/15 14:46:25 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved