1, in the react project to install react-pdf dependency package
It is recommended to install version 8.0.2 of react-pdf, if you install a higher version may appear some browser compatibility issues;
npm install [email protected] -S
1、PC use
1.1. Encapsulate a component:
import React, { useState } from 'react' import { Modal, Spin, Alert } from 'antd' import { Document, Page, pdfjs } from 'react-pdf' import 'react-pdf/dist/esm/Page/' import 'react-pdf/dist/esm/Page/'; // Configuration of the worker file = new URL('pdfjs-dist/build/', ).toString() interface PDFPreviewModalProps { fileName: string | null fileUrl: string | null // Incoming PDF file address onCancel: () => void // Callback to close the popup box } const PDFPreviewModal: <PDFPreviewModalProps> = ({ fileName, fileUrl, onCancel }) => { const [numPages, setNumPages] = useState<number | null>(null) const [pdfWidth, setPdfWidth] = useState<number>(600) // The default width is 600px const [loading, setLoading] = useState<boolean>(true) // Controlling the loading state const [error, setError] = useState<boolean>(false) // Control Load Error Status // Setting the number of pages when the PDF is loaded successfully const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => { setNumPages(numPages) setLoading(false) // Hide loading after successful loading } // Set error status when loading fails const onDocumentLoadError = () => { setLoading(false) setError(true) // Display error message when something goes wrong } // Get the width of the PDF page after loading const onPageLoadSuccess = ({ width }: { width: number }) => { setPdfWidth(width) } return ( <Modal title={`[${fileName}] preview`} open onCancel={onCancel} footer={null} width={pdfWidth + 100} style={{ top: 20 }} > {error ? ( <Alert message="Failed to load PDF file." type="error" showIcon /> ) : ( <> {loading && ( <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '80vh' }}> <Spin size="large" /> </div> )} {fileUrl && ( <> <div style={{ height: '88vh', overflowY: 'auto', padding: '24px' }}> <Document //file={new URL('/public/temp/DXF file request.pdf',).toString()} file={fileUrl} onLoadSuccess={onDocumentLoadSuccess} onLoadError={onDocumentLoadError} > {(new Array(numPages), (el, index) => ( <Page key={`page_${index + 1}`} pageNumber={index + 1} onLoadSuccess={onPageLoadSuccess} /> ))} </Document> </div> </> )} </> )} </Modal> ) } export default PDFPreviewModal
1.2. Introduce the component in the business code
import React, { useState, useEffect, useCallback } from 'react' import { Form } from 'antd' import { List } from 'antd' import PDFPreviewModal from '@/components/' const PdfTest = (props: any) => { const [previewFile, setPreviewFile] = useState<any>()
const onTestPdf = () => {
setPreviewFile({
fileName: '',
fileUrl: 'http://****/'
})
}return ( <div className="mrUp mrLink">
<div onClick={onTestPdf}>Test PreviewPDF</div>
{!!previewFile?.publicFileUrl && ( <PDFPreviewModal fileName={previewFile?.fileName} fileUrl={previewFile?.publicFileUrl} onCancel={() => setPreviewFile('')} /> )} </div> ) } export default PdfTest
2、H5 mobile use
Add zoom in, zoom out, previous page, next page to mobile;
2.1. Encapsulate a component:
import React, { useState } from 'react'; import { Button, Modal, Space, Toast, Divider } from 'antd-mobile' import { UpOutline, DownOutline, AddCircleOutline, MinusCircleOutline } from 'antd-mobile-icons' import { Document, Page, pdfjs } from 'react-pdf'; import 'react-pdf/dist/esm/Page/'; // Style Import import 'react-pdf/dist/esm/Page/' // Configuration of the worker file = new URL('pdfjs-dist/build/', ).toString() interface PDFPreviewModalProps { fileUrl: string | null; // Incoming PDF file address } const styleBtnDv = { display: 'flex', justifyContent: 'center', height: '1rem', alignItems: 'center', gap: '0.4rem', margin: '0.3rem 1rem', padding: '0 0.6rem', background: '#444', borderRadius: '0.5rem' } const styleBtn = { flex: 1, display: 'flex', justifyContent: 'center', height: '0.6rem', alignItems: 'center', } // PDF preview function const PDFViwer: <PDFPreviewModalProps> = ({ fileUrl }) => { const [pageNumber, setPageNumber] = useState(1); const [numPages, setNumPages] = useState(1); const [scale, setScale] = useState(0.65); // Setting the number of pages when the PDF is loaded successfully const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => { setNumPages(numPages); }; //preceding page function lastPage() { if (pageNumber == 1) { ({ content: 'Already on the first page' }) return; } const page = pageNumber - 1; setPageNumber(page); } //next page function nextPage() { if (pageNumber == numPages) { ("It's the last page."); return; } const page = pageNumber + 1; setPageNumber(page); } //downsize function pageZoomOut() { if (scale <= 0.3) { ("Minimized."); return; } const newScale = scale - 0.1; setScale(newScale); } //zoom in function pageZoomIn() { if (scale >= 5) { ("Amplified to maximum."); return; } const newScale = scale + 0.1; setScale(newScale); } return ( <div> {/* Preview PDF file*/} {fileUrl ? ( <div style={{ height: 'calc(100vh - 4.5rem)', overflowY: 'auto', padding: '24px' }}> <Document // Write the address of the dead pdf file for local testing, packaged for submission before the need to comment out // file={new URL("/public/temp/AI-sales-assistant-broadband&packages&war-new.pdf", ).toString()} // Real incoming pdf address file={fileUrl} onLoadSuccess={onDocumentLoadSuccess} > <Page pageNumber={pageNumber} scale={scale} /> </Document> </div> ) : ( <p>No document selected</p> )} <div style={styleBtnDv}> <div style={styleBtn} onClick={lastPage}><UpOutline color='#fff' fontSize={'0.6rem'} /></div> <div style={{ color: '#fff', fontSize: '0.35rem', ...styleBtn }}>{pageNumber}/{numPages}</div> <div style={styleBtn} onClick={nextPage}><DownOutline color='#fff' fontSize={'0.6rem'} /></div> <div style={styleBtn} onClick={pageZoomIn}><AddCircleOutline color='#fff' fontSize={'0.6rem'} /></div> <div style={styleBtn} onClick={pageZoomOut}><MinusCircleOutline color='#fff' fontSize={'0.6rem'} /></div> </div> </div> ); }; export default PDFViwer;
2.2. Introduce the component in the business code
import React, { useMemo, useRef, useState } from 'react' import { ErrorBlock, Swiper, SwiperRef, Popup, } from 'antd-mobile' import PDFViwer from '@/components/PDFViwer'; const ellipsis1 = { "white-space": "nowrap", "overflow": "hidden", "text-overflow": "ellipsis", } const IntroduceDocList = (props: any) => { const { loading, introduceDocList } = props // const introduceDocList = [ // {publicFileUrl: '/public/temp/DXF File Requirements.pdf', fileName: 'DXF File Requirements.pdf'}, // {publicFileUrl: '/public/temp/AI-Sales-Assistant-Broadband&Packages&BattleNew.pdf', fileName: 'AI-Sales-Assistant-Broadband&Packages&BattleNew.pdf'}, // ]
const [introduceDocList, setIntroduceDocList] = useState({
{publicFileUrl: 'http://****/', fileName:''},
{publicFileUrl: 'http://****/', fileName:''},
});
const [pdf, setPdf] = useState({ id: 1 }); const [showPdfViwer, setShowPdfViwer] = useState(false) const onOpenPdfViewer = (item) => { (item); setPdf(item); setShowPdfViwer(true); } return ( <div> { introduceDocList?.map(item => ( <div data-url={item?.publicFileUrl} style={{ marginBottom: '0.3rem', fontSize: '0.4rem' }}> <span style={{color:'#0B75FF'}} onClick={() => onOpenPdfViewer(item)}>{}</span> </div> )) } <Popup position='right' visible={showPdfViwer} showCloseButton bodyStyle={{ width: '100%' }} destroyOnClose={true} onClose={() => { setShowPdfViwer(false) setPdf({ id: 1 }) }} > <div style={{ padding: '0.3rem 1rem', fontSize: '0.35rem', fontWeight: 600, textAlign:'center', ...ellipsis1 }}>{pdf?.fileName}</div> <div style={{ height: '100%' }} data-url={pdf?.publicFileUrl}> <PDFViwer fileUrl={pdf?.publicFileUrl} /> </div> </Popup> </div> ) } export default IntroduceDocList
Rendering:
Note: block in the local development, if the preview of the pdf file address is the address of the line, it will report cross-domain issues, the need for server-side solution to cross-domain issues.