Location>code7788 >text

react-pdf preview online PDF use

Popularity:949 ℃/2024-09-19 11:35:49

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.