关于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;

总结

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

相关文章

  • 详解webpack2+node+react+babel实现热加载(hmr)

    详解webpack2+node+react+babel实现热加载(hmr)

    这篇文章主要介绍了详解webpack2+node+react+babel实现热加载(hmr) ,非常具有实用价值,需要的朋友可以参考下
    2017-08-08
  • React触发render的实现方法

    React触发render的实现方法

    这篇文章主要介绍了React触发render的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • React Hooks--useEffect代替常用生命周期函数方式

    React Hooks--useEffect代替常用生命周期函数方式

    这篇文章主要介绍了React Hooks--useEffect代替常用生命周期函数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • react实现拖拽模态框

    react实现拖拽模态框

    这篇文章主要为大家详细介绍了react实现拖拽模态框,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • 在React中编写class样式的方法总结

    在React中编写class样式的方法总结

    在TypeScript (TSX) 中编写 CSS 样式类有几种方法,包括使用纯 CSS、CSS Modules、Styled Components 等,本文给大家介绍了几种常见方法的示例,通过代码示例讲解的非常详细,需要的朋友可以参考下
    2024-07-07
  • ForwardRef useImperativeHandle方法demo

    ForwardRef useImperativeHandle方法demo

    这篇文章主要为大家介绍了ForwardRef useImperativeHandle方法demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 使用React-Router实现前端路由鉴权的示例代码

    使用React-Router实现前端路由鉴权的示例代码

    这篇文章主要介绍了使用React-Router实现前端路由鉴权的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • 前端 react 实现图片上传前压缩(缩率图)

    前端 react 实现图片上传前压缩(缩率图)

    这篇文章主要介绍了前端 react 实现图片上传前压缩(缩率图),本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • React Native时间转换格式工具类分享

    React Native时间转换格式工具类分享

    这篇文章主要为大家分享了React Native时间转换格式工具类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • React从命令式编程到声明式编程的原理解析

    React从命令式编程到声明式编程的原理解析

    这篇文章主要介绍了React从命令式编程到声明式编程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09

最新评论