首页 > 其他分享 >react-pdf 实现pdf文件预览功能

react-pdf 实现pdf文件预览功能

时间:2024-03-08 17:00:11浏览次数:19  
标签:current const 预览 react import pdf pageCurrentRef

参考文档

  https://www.npmjs.com/package/react-pdf
  https://github.com/wojtekmaj/react-pdf#readme

 

一、概述

react项目中,很多时候(尤其是需展示报告的页面)会遇到需要预览pdf文件的需求。而据调研,使用react-pdf插件可以很好地实现这个功能。

 

 

二、操作步骤

1. 安装

yarn add react-pdf  或 npm install --save react-pdf引入

 

2. 新建一个 PdfViewer.jsx 的公共组件,作为pdf预览的封装文件

import React, { useEffect, useState, useRef } from 'react';
import { Spin, Tooltip, Input } from 'antd';
import { LeftOutlined, RightOutlined, ZoomInOutlined, ZoomOutOutlined } from '@ant-design/icons';

import { Document, Page, pdfjs } from "react-pdf";
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
import 'react-pdf/dist/esm/Page/TextLayer.css';
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;

const PageCom = (props) => {
  const [filePath, setFilePath] = useState(null);

  const [pageCurrent, setPageCurrent] = useState(1);
  const pageCurrentRef = useRef(pageCurrent); 

  const [pageTotal, setPageTotal] = useState(1);
  const pageTotalRef = useRef(pageTotal); 

  const [pageWidth, setPageWidth] = useState(960);
  const pageWidthRef = useRef(pageWidth);     

  useEffect(()=>{      
    setPageCurrent(1);
    pageCurrentRef.current= 1;

    setFilePath(props.filePath);    
  },[props.filePath])  

  const prevPage = () => {
    if (pageCurrentRef.current == 1) { return; }
    setPageCurrent(pageCurrentRef.current - 1);
    pageCurrentRef.current= pageCurrentRef.current - 1;
  };

  const nextPage = () => {
    if (pageCurrentRef.current == pageTotalRef.current) {
      return;
    }
    
    setPageCurrent(pageCurrentRef.current + 1);
    pageCurrentRef.current= pageCurrentRef.current + 1;
  };

  const pageNumChange = e => {
    let value = Number(e.target.value);
    let value2 = 1;

    if(value<=0){
        value2 = 1;
    } else if(value >= pageTotalRef.current){
        value2 = pageTotalRef.current;
    } else {
        value2 = value;
    }
  
    setPageCurrent(value);
    pageCurrentRef.current= value;
  };

  const toPage = e => {
    console.log('toPage====',e)
    let value = Number(e.target.value);
    let value2 = value;

    if(value<=0){
        value2 = 1;
    } else if(value >= pageTotalRef.current){
        value2 = pageTotalRef.current;
    } else {
        value2 = value;
    }
    setPageCurrent(value2);
    pageCurrentRef.current= value2;
  };

  const pageZoomOut = () => {
    if (pageWidthRef.current <= 960) {
      return
    }
    const pageWidth = pageWidthRef.current * 0.8;    
    setPageWidth(pageWidth);    
    pageWidthRef.current = pageWidth;
  };

  const pageZoomIn = () => {
    const pageWidth = pageWidthRef.current * 1.2
    setPageWidth(pageWidth);    
    pageWidthRef.current = pageWidth;
  };

  const onDocumentLoadSuccess = (args) => {
    setPageTotal(args.numPages);
    pageTotalRef.current = args.numPages;
  };

  return (
    <div className="pdfViewer-wrapper">
      {filePath?(<>
        <div className="pageContainer">
          <Document file={filePath} onl oadSuccess={ onDocumentLoadSuccess }  loading={<Spin size="large" />} >
            <Page pageNumber={pageCurrent} width={pageWidth} loading={<Spin size="large" />}  />
          </Document>
        </div>

        <div className="pageTool">
          <Tooltip title={pageCurrent == 1 ? "已是第一页" : "上一页"}>
            <LeftOutlined onClick={prevPage} />
          </Tooltip>
          <Input value={pageCurrent} onChange={ pageNumChange } onPressEnter={ toPage } type="number" /> / {pageTotal}
          <Tooltip title={pageCurrent == pageTotal ? "已是最后一页" : "下一页"}>
            <RightOutlined onClick={ nextPage } />
          </Tooltip>
          <Tooltip title="放大">
            <ZoomInOutlined onClick={ pageZoomIn } />
          </Tooltip>
          <Tooltip title="缩小">
            <ZoomOutOutlined onClick={ pageZoomOut } />
          </Tooltip>       
        </div>
      </>):(<div className="empty-wrapper">未指定PDF文件!</div>)}
    </div>
  );  
};

export default PageCom;

 

3. 在需要pdf文件预览的页面,进行处理

import React, { useEffect, useState, useRef } from 'react';
import pdfPath from '@/lib/demo.pdf'; import PdfViewer from './PdfViewer.jsx'; import '@/styles/report.less'; import axios from 'axios' const PageCom = (props) => { const [filePath, setFilePath] = useState(null); useEffect(()=>{ if(token){
       // setFilePath(filePath); //本地测试文件url
       // 或 getData(); //远程获取文件url } },[token]) /* 获取报告文件流数据 */ const getData = ()=>{ axios.get('/api/getPdf', { responseType: 'blob' }).then(res => { const blob = new Blob([res.data], { type: res.headers["content-type"] }); let URL = window.URL || window.webkitURL; let href = URL.createObjectURL(blob); setFilePath(href); }) };
return <div className="page-fjhScreenReport"> {/* 查询条件 */} {/* ... */} {/* 文档内容 */} <div className="con-wrapper"> <PdfViewer filePath={filePath}/> </div> </div>; }; export default PageCom;

  

4. 对pdf预览样式进行处理 

.pdfViewer-wrapper {
        background:#f5f5f5;
        display: flex;
        justify-content: center;
        height: 100vh;
        padding: 10px 0;
        overflow: auto;
        box-sizing: border-box;

        .empty-wrapper{
            padding: 100px 0 50px;
            text-align: center;
            font-size: 20px;
            letter-spacing: 2px;
            color: #999;
        }

        .pageContainer {            
            z-index: 1;
            box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 4px 0px;
            width:max-content;
            max-width:100%;
            &:after{
                content:'';
                position: relative;
                display: block;
                height:110px;
                clear:both;
                overflow: hidden;
            }
        }

        .pageTool{
            z-index: 99;
            font-size: 18px;
            position: absolute;
            bottom: 10px;
            background: rgb(66, 66, 66);
            color: white;
            padding: 8px 15px;
            border-radius: 15px;
            display: flex;
            justify-content: center;
            align-items: center;
            .anticon{margin: 0 10px;}
            i{
            padding: 5px;
            margin:0 5px;
            &:hover{
                background: #333;
            }
            }
            input{
            display: inline-block;
            width: 50px;
            text-align: center;
            margin-right: 10px;
            height: 24px;
            }
            input::-webkit-outer-spin-button,
            input::-webkit-inner-spin-button {
            -webkit-appearance: none;
            }
            input[type="number"]{
            -moz-appearance: textfield;
            }
        }
}

 

注释:pdf 文件因为字体等原因,可能导致不完全加载,详见参考文档(不过用通用字体生成的pdf一般是没有问题的)!

 

 

 

翻译

搜索

复制

标签:current,const,预览,react,import,pdf,pageCurrentRef
From: https://www.cnblogs.com/bky419/p/18060831

相关文章

  • echarts报表生成pdf文件
    完整的demo如下:<!DOCTYPEhtml><html><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><title>Balken</title><scriptsrc="static/echarts/echarts.js"......
  • 关于rails打印pdf prawn gem的使用
    1.安装gem  gem'prawn'gem'prawn-table' 2.由于prawn包中不支持打印中文,所以需要将windows电脑路径下的字体复制到gem的安装路径下windows字体路径:C:\Windows\Fontsgem中安装路径:/Users/zhoukong/.rvm/gems/jruby-9.0.0.0.pre1@rails4/gems/prawn-2.2.2/data/fonts......
  • jsPDF 文字、图片生成PDF(解决中文乱码)
    JSPDF官网在线演示地址(不支持中文)思源黑体字体库下载地址:https://gitee.com/ABCpril/SourceHansTtf   https://github.com/adobe-fonts/source-han-sans/blob/release/README.md (后面一个是完整的包、比较大,一般用前面一种)JSPDF支持中文(思源黑体)采坑之旅,JSPDF中文字体......
  • React设计原理解密及核心源码解读
    一、React基础回顾1、react介绍React是一个用于构建用户界面的JavaScript库,它只负责应用的视图层,帮助开发人员构建快速且交互式的web应用程序。React使用组件的方式构建用户界面。2、JSX语法回顾在React中使用JSX语法描述用户界面,它是一种JavaScript语法扩展......
  • 【专题】2023年中国奢侈品市场数字化趋势洞察报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=33672原文出处:拓端数据部落公众号2022年,中国的奢侈品消费市场一直处于不断变化和挑战之中,但随着2023年的到来,中国正在全面复苏,市场也充满了机遇和想象空间。自2019年以来,奢侈品品牌一直在中国尝试本地化和数字化策略,将中国的奢侈品消费者与国内市......
  • 【专题】大健康趋势洞察报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=33947原文出处:拓端数据部落公众号在疫情的背景下,健康话题备受关注,民众对健康的意识不断提高,这促使了健康产业的蓬勃发展。阅读原文,获取专题报告合集全文,解锁文末242份大健康相关行业研究报告。首先,国家对中药材产业的扶持力度不断增强,推动了中药......
  • React — Redux详解
    Redux是一个用于JavaScript应用程序的状态管理库。它可以帮助您管理应用程序中的状态,并确保状态的一致性和可预测性。Redux主要用于处理大型应用程序中的复杂状态逻辑,例如跨组件共享状态、处理异步数据流等。Redux的核心概念包括:Store(存储):Redux应用程序的状态......
  • 如何将PDF文件无损压缩到更小?
    有时候我们为了提高文件传输速度,会适当压缩一下PDF文件大小,但很多朋友不知道怎么将PDF文件压缩的小一点,考虑到下载安装软件比较复杂还只能电脑使用,下面就给大家分享二个在线就能PDF压缩得方法,一起来了解下吧。方法一:ilovepdf中文版ilovepdf中文版是一款专业的在线PDF转换工具,网......
  • 值得收藏的几款免费pdf转成图片的在线工具
    如何将PDF转成图片?在数字化时代,PDF文件已成为我们日常生活和工作中不可或缺的一部分。有时我们也需要将PDF文件转换为图片格式,以便更方便地分享、编辑或打印。接下来为你推荐几款备受好评的PDF转图片在线工具,帮助你轻松转换各种格式文件。1.ilovepdf在线工具中文版ilovepdf中文......
  • 美能达423一体机打印pdf文件报错
    美能达423一体机打印pdf文件报错,出纸一张,左上角有小字显示PCL6err。打印一直很正常,同事打印了三页内有图片表格的pdf文件只出纸一张,左上角有小字显示PCL6err,开始的想法是不可能啊,再试,一样,重新打开文档,再试,一样,换一个电脑打印同一个pdf文档,试了一样,wps,acrobat,edge试了也一样,笨......