关于React项目中的PDF展示解决方案

 更新时间:2024年07月02日 09:52:16   作者:草晚晴  
这篇文章主要介绍了关于React项目中的PDF展示解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

本文将梳理两种方案,涉及两个库react-pdfpdf.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展示

  • 编译好的pdfjs可直接下载,也可去官网下载
  • 需要先将编译好的pdfjs版本放在react项目的public目录
├── 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;

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • React版本18.xx降低为17.xx的方法实现

    React版本18.xx降低为17.xx的方法实现

    由于现在react默认创建是18.xx版本,但是我们现在大多使用的还是17.xx或者更低的版本,于是要对react版本进行降级,本文主要介绍了React版本18.xx降低为17.xx的方法实现,感兴趣的可以了解一下
    2023-11-11
  • React中的生命周期和子组件

    React中的生命周期和子组件

    这篇文章主要介绍了React中的生命周期和子组件,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下
    2022-08-08
  • 详解React setState数据更新机制

    详解React setState数据更新机制

    这篇文章主要介绍了React setState数据更新机制的相关资料,帮助大家更好的理解和学习使用React框架,感兴趣的朋友可以了解下
    2021-04-04
  • React useCallback钩子的作用方法demo

    React useCallback钩子的作用方法demo

    这篇文章主要为大家介绍了React useCallback钩子的作用方法demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • React通过conetxt实现多组件传值功能

    React通过conetxt实现多组件传值功能

    Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。本文给大家介绍React通过conetxt实现多组件传值功能,感兴趣的朋友一起看看吧
    2021-10-10
  • React引入css的几种方式及应用小结

    React引入css的几种方式及应用小结

    这篇文章主要介绍了React引入css的几种方式及应用小结,操作styled组件的样式属性,可在组件标签上定义属性、也可以通过attrs定义属性,本文通过实例代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • React组件的生命周期详细描述

    React组件的生命周期详细描述

    本篇文章主要介绍了React组件生命周期,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-10-10
  • React Context原理深入理解源码示例分析

    React Context原理深入理解源码示例分析

    这篇文章主要为大家介绍了React Context原理深入理解源码示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • 深入理解React中es6创建组件this的方法

    深入理解React中es6创建组件this的方法

    this的本质可以这样说,this跟作用域无关的,只跟执行上下文有关。接下来通过本文给大家介绍React中es6创建组件this的方法,非常不错,感兴趣的朋友一起看看吧
    2016-08-08
  • React Fiber结构的创建步骤

    React Fiber结构的创建步骤

    这篇文章主要介绍了React Fiber结构的创建步骤,帮助大家更好的理解和学习使用React,感兴趣的朋友可以了解下
    2021-04-04

最新评论