当前位置: 首页 > 工具软件 > React-Total > 使用案例 >

react react-pdf实现在线pdf加载 翻页加载、下拉滚动加载

白弘伟
2023-12-01

1.导入react-pdf
npm i react-pdf --save
import { Document, Page, pdfjs } from ‘react-pdf’;
pdfjs.GlobalWorkerOptions.workerSrc = ‘pdf.worker.min.js’; //1.解决报错

Uncaught SyntaxError: Unexpected token <
index.js:1452 

Error: Setting up fake worker failed: "Cannot read property 'WorkerMessageHandler' of undefined".
    at pdf.js:10999

如果任然报错 替换

pdfjs.GlobalWorkerOptions.workerSrc = //cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js;// 版本问题
2.简易版—点击翻页预览

<div className={styles.pdfModal}>
            <div className={styles.pdf_container} 
                onContextMenu={preventDefault}
            >
                <Document
                    file={file}      
                    className={styles.pdf_document}
                    loading={documentLoading}     //自定义加载内容
                    onLoadSuccess={documentOnLoadSuccess}   //加载完成
                    noData={noData}   //空内容显示

                >             <Page                 className={styles.pdf_page}
                      pageNumber={pdfIndex}
                          height={ 800 }  //固定高度             />          </Document>
            </div>
            <div className={styles.btnContainer}>
                <Pagination             defaultCurrent={1}             total={numpages}             onChange={changePage}          />
            </div>    </div>
//页面加载完回调
    const documentOnLoadSuccess = (pdf: any) => {
        console.log('加载完', pdf)
        let numPages = pdf.numPages;
        setNumPages(numPages)
    }
  //自定义加载loading
    const documentLoading = () => {
        return <div>Please wait!</div>;
    }
  //请求获取pdf的地址
    useEffect(() => {
        api.getpreview(params).then((res) => {
            if (res && res.byteLength) {
                setFile(res);
            } else {
                setNoData(<div>no pdf</div>)
            }
        });
    }, [])

    //阻止右键默认事件(禁止下载)
    const preventDefault = (e: any) => {
            e.preventDefault()
    }

    //点击翻页
    const [pdfIndex, setPdfIndex] = useState(1)
    const changPage = (page)=>{    setPdfIndex(page)  }
//获取pdf地址接口//返回数据类型
  responseType: 'arraybuffer'

  responseType: 'blob'
 
  注:数据类型转换:https://blog.csdn.net/weixin_41849462/article/details/103409341
  blob转换成base64:
    let reader = new FileReader()
    reader.readAsDataUrl(blob)
    reader.onload = (e)=>{
      resolve(e.target.result)
    }
 
 //数据拦截

 
  interceptor(res: any) {
      console.log('res', res);
      if (res?.headers['content-type']?.includes('pdf')) {
        return Promise.resolve(res.data);
      }
   }

下拉展示pdf
其实就是一口气遍历渲染出来,创建了一个长度为总页数numPages的数组进行map,用index做页数的请求,不过index基于0,pageNumber基于1,因此index需要+1。
示例比较粗糙,一口气展示,展示较少内容的pdf时没有什么问题,如果pdf页数过多会出现性能问题,可以自行考虑加载方法(例如每滑动十页进行下面十页的加载)。

import React, { Component } from 'react';
import { Document, Page } from 'react-pdf';

export default class index extends Component {
  state = {
    numPages: null,
    pageNumber: 1,
  };
  onDocumentLoadSuccess = ({ numPages }) => {
    this.setState({ numPages });
  };
  render() {
    const { pageNumber, numPages } = this.state;
    return (
      <div>
        <Document
          file={'/pdf/555.pdf'}
          onLoadSuccess={this.onDocumentLoadSuccess}
        >
          {new Array(numPages).fill('').map((cur, index) => (
            <Page
              key={index}
              width={window.screen.width}
              pageNumber={index + 1}
            />
          ))}
        </Document>
      </div>
    );
  }
}

 类似资料: