关于React项目中的PDF展示解决方案
作者:草晚晴
这篇文章主要介绍了关于React项目中的PDF展示解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
本文将梳理两种方案,涉及两个库react-pdf
和pdf.js
,使用环境为ant-design-pro脚手架创建的项目。
使用iframe标签
1.不需要任何依赖的两种方式为
直接使用iframe标签展示pdf文件
<iframe src={fileUrl} width={'100%'} height={'100%'} style={{ minHeight: '80vh' }} />
其中fileUrl为需要展示pdf的文件地址,宽高和style均可自定义,下不赘述。
如果用户可以访问google,则可以使用如下地址:
<iframe src={`http://docs.google.com/gview?url=${fileUrl}&embedded=true`} width={'100%'} height={'100%'} style={{ minHeight: '80vh' }} />
其中fileUrl为需要展示pdf的文件地址,宽高和style均可自定义。
2.使用编译好的静态库pdf.js的viewer.html展示
├── config # umi 配置,包含路由,构建等配置 ├── mock # 本地模拟数据 ├── public # 将编译好的PDFJS放在这个目录下 │ └── favicon.png # Favicon ├── src │ ├── assets # 本地静态资源 │ ├── components # 业务通用组件 │ ├── e2e # 集成测试用例 │ ├── layouts # 通用布局 │ ├── models # 全局 dva model │ ├── pages # 业务页面入口和常用模板 │ ├── services # 后台接口服务 │ ├── utils # 工具库 │ ├── locales # 国际化资源 │ ├── global.less # 全局样式 │ └── global.ts # 全局 JS ├── tests # 测试工具 ├── README.md └── package.json
如下图所示:
在需要展示PDF文件的地方,使用如下src即可。
<iframe src={`pdfjs-2.2.228-dist/web/viewer.html?file=${fileUrl}`} width={'100%'} height={'100%'} style={{ minHeight: '80vh' }} />
使用react-pdf展示
import { Pagination } from 'antd'; import React, { useState } from 'react'; import { Document, Page } from 'react-pdf/dist/esm/entry.webpack'; // @ts-ignore const PdfViewer: React.FC<{ url: string }> = ({ url }) => { const [numPages, setNumPages] = useState(0); const [pageNumber, setPageNumber] = useState(1); // @ts-ignore const onDocumentLoadSuccess = (props: any) => { setNumPages(props?.numPages); }; const onChangePage = (page: any) => { setPageNumber(page); }; return ( <div> <div style={{ marginBottom: 4 }}> <a href={url} target={'_blank'} rel="noreferrer"> 查看当前文件 </a> </div> <Document file={url} onLoadSuccess={onDocumentLoadSuccess}> <Page pageNumber={pageNumber} /> </Document> <Pagination style={{ marginTop: 4, display: 'flex', justifyContent: 'flex-end' }} total={numPages} simple hideOnSinglePage showTotal={(total) => `共 ${total} 页`} current={pageNumber} pageSize={1} size="small" onChange={onChangePage} /> </div> ); }; export default PdfViewer;
pdfjs的另一种使用方式
import { useEffect, useRef, useState } from 'react'; const PDFJsViewer = ({ pdfUrl }: any) => { const pdfjsLib = require('pdfjs-dist/build/pdf.js'); const pdfjsWorker = require('pdfjs-dist/build/pdf.worker.entry.js'); pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker; const canvasRef = useRef(null); const [scale, setScale] = useState(1); const [offset, setOffset] = useState({ x: 0, y: 0 }); const handleWheel = (e: any) => { if (e.deltaY < 0) { setScale((prevScale) => Math.min(prevScale + 0.1, 3)); } else { setScale((prevScale) => Math.max(prevScale - 0.1, 0.5)); } }; const handleMouseDown = (e: any) => { const initialX = e.clientX - offset.x; const initialY = e.clientY - offset.y; const handleMouseMove = (e: any) => { const newX = e.clientX - initialX; const newY = e.clientY - initialY; setOffset({ x: newX, y: newY }); }; const handleMouseUp = () => { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); }; document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); }; useEffect(() => { const canvas = canvasRef.current; //@ts-ignore const ctx = canvas.getContext('2d'); const loadingTask = pdfjsLib.getDocument(pdfUrl); loadingTask.promise.then((pdf: any) => { pdf.getPage(1).then((page: any) => { const viewport = page.getViewport({ scale: scale }); //@ts-ignore canvas.height = viewport.height; //@ts-ignore canvas.width = viewport.width; ctx.setTransform(1, 0, 0, 1, 0, 0); //@ts-ignore ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.setTransform(scale, 0, 0, scale, offset.x, offset.y); const renderContext = { canvasContext: ctx, viewport: viewport, }; page.render(renderContext); }); }); }, [pdfUrl, scale, offset]); return <canvas ref={canvasRef} onWheel={handleWheel} onMouseDown={handleMouseDown}></canvas>; }; export default PDFJsViewer;
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。