1、在react项目中安装react-pdf依赖包

建议安装8.0.2版本的react-pdf,如果安装更高版本的可能出现一些浏览器的兼容性问题;

npm install react-pdf@8.0.2 -S

1、PC端的使用

1.1、封装一个组件:PdfViewModal.tsx

import React, { useState } from 'react'
import { Modal, Spin, Alert } from 'antd'
import { Document, Page, pdfjs } from 'react-pdf'
import 'react-pdf/dist/esm/Page/AnnotationLayer.css'
import 'react-pdf/dist/esm/Page/TextLayer.css'; // 配置 PDF.js 的 worker 文件
pdfjs.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.js', import.meta.url).toString() interface PDFPreviewModalProps {
fileName: string | null
fileUrl: string | null // 传入的 PDF 文件地址
onCancel: () => void // 关闭弹框的回调
} const PDFPreviewModal: React.FC<PDFPreviewModalProps> = ({ fileName, fileUrl, onCancel }) => {
const [numPages, setNumPages] = useState<number | null>(null)
const [pdfWidth, setPdfWidth] = useState<number>(600) // 默认宽度为 600px
const [loading, setLoading] = useState<boolean>(true) // 控制加载状态
const [error, setError] = useState<boolean>(false) // 控制加载错误状态 // 当 PDF 加载成功时,设置页面数量
const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {
setNumPages(numPages)
setLoading(false) // 加载成功后,隐藏 loading
} // 加载失败时,设置错误状态
const onDocumentLoadError = () => {
setLoading(false)
setError(true) // 出错时显示错误提示
} // 获取 PDF 页面加载后的宽度
const onPageLoadSuccess = ({ width }: { width: number }) => {
setPdfWidth(width)
} return (
<Modal
title={`【${fileName}】预览`}
open
onCancel={onCancel}
footer={null}
width={pdfWidth + 100}
style={{ top: 20 }}
>
{error ? (
<Alert message="加载 PDF 文件失败" 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文件要求.pdf',import.meta.url).toString()}
file={fileUrl}
onLoadSuccess={onDocumentLoadSuccess}
onLoadError={onDocumentLoadError}
>
{Array.from(new Array(numPages), (el, index) => (
<Page key={`page_${index + 1}`} pageNumber={index + 1} onLoadSuccess={onPageLoadSuccess} />
))}
</Document>
</div>
</>
)}
</>
)}
</Modal>
)
} export default PDFPreviewModal

1.2、业务代码中引入该组件

import React, { useState, useEffect, useCallback } from 'react'
import { Form } from 'antd'
import { List } from 'antd'
import PDFPreviewModal from '@/components/PdfViewModal.tsx' const PdfTest = (props: any) => {
const [previewFile, setPreviewFile] = useState<any>()

const onTestPdf = () => {
  setPreviewFile({
    fileName: 'abc.pdf',
    fileUrl: 'http://****/abc.pdf'
  })
}return (
<div className="mrUp mrLink">
   <div onClick={onTestPdf}>测试预览PDF</div>

{!!previewFile?.publicFileUrl && (
<PDFPreviewModal
fileName={previewFile?.fileName}
fileUrl={previewFile?.publicFileUrl}
onCancel={() => setPreviewFile('')}
/>
)}
</div>
)
} export default PdfTest

2、H5移动端的使用

移动端加入放大、缩小、上一页、下一页的功能;

2.1、封装一个组件:PDFViwer.tsx

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/AnnotationLayer.css'; // 样式导入
import 'react-pdf/dist/esm/Page/TextLayer.css' // 配置 PDF.js 的 worker 文件
pdfjs.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.js', import.meta.url).toString() interface PDFPreviewModalProps {
fileUrl: string | null; // 传入的 PDF 文件地址
} 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预览功能
const PDFViwer: React.FC<PDFPreviewModalProps> = ({ fileUrl }) => {
const [pageNumber, setPageNumber] = useState(1);
const [numPages, setNumPages] = useState(1);
const [scale, setScale] = useState(0.65); // 当 PDF 加载成功时,设置页面数量
const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {
setNumPages(numPages);
}; //上一页
function lastPage() { if (pageNumber == 1) {
Toast.show({
content: '已是第一页'
})
return;
}
const page = pageNumber - 1;
setPageNumber(page);
}
//下一页
function nextPage() {
if (pageNumber == numPages) {
Toast.show("已是最后一页");
return;
}
const page = pageNumber + 1;
setPageNumber(page);
}
//缩小
function pageZoomOut() {
if (scale <= 0.3) {
Toast.show("已缩放至最小");
return;
}
const newScale = scale - 0.1;
setScale(newScale);
} //放大
function pageZoomIn() {
if (scale >= 5) {
Toast.show("已放大至最大");
return;
}
const newScale = scale + 0.1;
setScale(newScale);
} return (
<div>
{/* 预览 PDF 文件 */}
{fileUrl ? (
<div style={{ height: 'calc(100vh - 4.5rem)', overflowY: 'auto', padding: '24px' }}>
<Document
// 写死的pdf文件地址,用于本地测试使用,打包提交前需要注释掉
// file={new URL("/public/temp/AI销售助手-宽带&套餐&战新.pdf", import.meta.url).toString()}
// 真实传入的pdf地址
file={fileUrl}
onLoadSuccess={onDocumentLoadSuccess}
>
<Page pageNumber={pageNumber} scale={scale} />
</Document>
</div>
) : (
<p>没有选择文件</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、业务代码中引入该组件

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文件要求.pdf', fileName:'DXF文件要求.pdf'},
// {publicFileUrl: '/public/temp/AI销售助手-宽带&套餐&战新.pdf', fileName:'AI销售助手-宽带&套餐&战新.pdf'},
// ]

const [introduceDocList, setIntroduceDocList] = useState({
  {publicFileUrl: 'http://****/abc.pdf', fileName:'abc.pdf'},
{publicFileUrl: 'http://****/def.pdf', fileName:'def.pdf'},
});

const [pdf, setPdf] = useState({ id: 1 });
const [showPdfViwer, setShowPdfViwer] = useState(false) const onOpenPdfViewer = (item) => {
console.log(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)}>{item.fileName}</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

效果图:

注意:挡在本地开发时,如果预览的pdf文件地址是线上地址,则会报跨域的问题,需要服务端解决跨域问题。

react-pdf预览在线PDF的使用的更多相关文章

  1. axios 下载文件流或者预览在线pdf

    问题: 后端返回文件流,前端使用axios下载或者在线预览 下载文件流 import axios from 'axios' // 设置响应类型为blob axios.get('/api/app/xxx ...

  2. pdf预览(pdf.js)

    开门见山,pdf.js是Mozilla(缩写MF或MoFo)全称Mozilla基金会,下面的插件.现在社区非常活跃. Mozilla是为支持和领导开源的Mozilla项目而设立的一个非营利组织 下载地 ...

  3. Office在线预览及PDF在线预览的实现方式史上最全大集合

    Office在线预览及PDF在线预览的实现方式大集合 一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office2007以上版本的一个PDF插件SaveAsPD ...

  4. Office在线预览及PDF在线预览的实现方式大集合

    一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office2007以上版本的一个PDF插件SaveAsPDFandXPS.exe可以导出PDF文件,然后再利用免 ...

  5. Office在线预览及PDF在线预览的实现方式

    原文链接:http://www.officeweb365.com/officetoview.html 一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office ...

  6. java原装代码完成pdf在线预览和pdf打印及下载

    这是我在工作中,遇到这样需求,完成需求后,总结的成果,就当做是工作笔记,以免日后忘记,当然,能帮助到别人是最好的啦! 下面进入正题: 前提准备: 1. 项目中至少需要引入的jar包,注意版本: a)  ...

  7. 浏览器实现PDF预览

    1.使用jquery.media.js预览PDF <!DOCTYPE html> <html> <head> <meta charset="utf- ...

  8. Android原生PDF功能实现:PDF阅读、PDF页面跳转、PDF手势伸缩、PDF目录树、PDF预览缩略图

    1.背景 近期,公司希望实现安卓原生端的PDF功能,要求:高效.实用. 经过两天的调研.编码,实现了一个简单Demo,如上图所示. 关于安卓原生端的PDF功能实现,技术点还是很多的,为了咱们安卓开发的 ...

  9. PDF预览之PDFObject.js总结

    get from:PDF预览之PDFObject.js总结   PDFObject.js - 将PDF嵌入到一个div内,而不是占据整个页面(要求浏览器支持显示PDF,不支持,可配置PDF.js来实现 ...

  10. Pdf预览功能实现(asp.net)

    asp.net中使用 1.pdf预览功能实现的插件是pdfjs-1.5.188-dist //引入插件中相关的文件以及jquery文件 @section css{ <link rel=" ...

随机推荐

  1. elementplus django drf 如何做到确认单据禁止删除

    elementplus django drf 如何做到确认单据禁止删除     要在Django和Django Rest Framework(DRF)中实现禁止删除确认单据的功能,你可以通过以下步骤来 ...

  2. [MAUI 项目实战] 笔记App(二):数据库设计

    @ 目录 Sqlite配置 创建实体 笔记实体类 笔记分组实体 笔记片段实体 笔记片段负载实体 笔记片段仓库实体 笔记模板(场景)实体 笔记片段模板实体 笔记片段模板负载实体 配置EF 创建映射 迁移 ...

  3. 前缀函数及 Knuth–Morris–Pratt 算法学习笔记

    \(\text{1 引言 Preface}\) 对于形如以下的问题: 给予一个模式串 \(T\) 和主串 \(S\),在主串中寻找 \(T\). 我们称之为字符串匹配. 很显然朴素算法时间复杂度是 \ ...

  4. php 模型浏览器

    docker安装 文档:https://github.com/SeleniumHQ/docker-selenium docker run -d -p 4444:4444 -p 7900:7900 -- ...

  5. scratch源码下载 | 几何冲刺

    程序说明: <几何冲刺>是一款基于Scratch平台开发的跑酷类游戏程序.在这个游戏中,玩家控制一个黄色的小方块,在快速向前冲刺的过程中躲避各种障碍物.通过按下键盘上的上方向键,玩家可以操 ...

  6. 百度翻译network里没有sug(文章发布时间2022年10月)

    百度翻译已经更新,现在的百度翻译分为两个阶段翻译,第一个阶段识别你的翻译字符是什么类型语言 第二阶段生成随机sign加携带token以post表单方式上传数据,返回json数据 尚硅谷在B站发布的的爬 ...

  7. 加压测试TPS上不去的性能分析

    加压测试TPS上不去的性能分析 阶梯式加压测试接口异常可能存在的原因: 压力机本身性能测试的瓶颈 分析:单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,也会间接影响TPS ,可以通过进行分布 ...

  8. wordpress站点转移

    title: wordpress站点转移 date: 2024/7/13 11:11:11 tag: linux学习 categories: wordpress建设 description: 搭建后的 ...

  9. 【JS】02 基础语法

    JS的引入方式: 第一种: 就是我们在HTML标签中使用script标签,然后在这个标签中可以书写JS代码 type="text/javascript"  可以不用写,浏览器会根据 ...

  10. 【转载】 tf.image.sample_distorted_bounding_box (为图像生成单个随机变形的边界框)

    原文地址: https://blog.csdn.net/tz_zs/article/details/77920116 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上 ...