react-pdf预览在线PDF的使用
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的使用的更多相关文章
- axios 下载文件流或者预览在线pdf
问题: 后端返回文件流,前端使用axios下载或者在线预览 下载文件流 import axios from 'axios' // 设置响应类型为blob axios.get('/api/app/xxx ...
- pdf预览(pdf.js)
开门见山,pdf.js是Mozilla(缩写MF或MoFo)全称Mozilla基金会,下面的插件.现在社区非常活跃. Mozilla是为支持和领导开源的Mozilla项目而设立的一个非营利组织 下载地 ...
- Office在线预览及PDF在线预览的实现方式史上最全大集合
Office在线预览及PDF在线预览的实现方式大集合 一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office2007以上版本的一个PDF插件SaveAsPD ...
- Office在线预览及PDF在线预览的实现方式大集合
一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office2007以上版本的一个PDF插件SaveAsPDFandXPS.exe可以导出PDF文件,然后再利用免 ...
- Office在线预览及PDF在线预览的实现方式
原文链接:http://www.officeweb365.com/officetoview.html 一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office ...
- java原装代码完成pdf在线预览和pdf打印及下载
这是我在工作中,遇到这样需求,完成需求后,总结的成果,就当做是工作笔记,以免日后忘记,当然,能帮助到别人是最好的啦! 下面进入正题: 前提准备: 1. 项目中至少需要引入的jar包,注意版本: a) ...
- 浏览器实现PDF预览
1.使用jquery.media.js预览PDF <!DOCTYPE html> <html> <head> <meta charset="utf- ...
- Android原生PDF功能实现:PDF阅读、PDF页面跳转、PDF手势伸缩、PDF目录树、PDF预览缩略图
1.背景 近期,公司希望实现安卓原生端的PDF功能,要求:高效.实用. 经过两天的调研.编码,实现了一个简单Demo,如上图所示. 关于安卓原生端的PDF功能实现,技术点还是很多的,为了咱们安卓开发的 ...
- PDF预览之PDFObject.js总结
get from:PDF预览之PDFObject.js总结 PDFObject.js - 将PDF嵌入到一个div内,而不是占据整个页面(要求浏览器支持显示PDF,不支持,可配置PDF.js来实现 ...
- Pdf预览功能实现(asp.net)
asp.net中使用 1.pdf预览功能实现的插件是pdfjs-1.5.188-dist //引入插件中相关的文件以及jquery文件 @section css{ <link rel=" ...
随机推荐
- [oeasy]python0122_日韩字符_日文假名_JIS_Shift_韩国谚文
日文假名和韩国谚文 回忆上次内容 上次回顾了非ascii的拉丁字符编码的进化过程 0-127 是 ascii 的领域 世界各地编码分布 拉丁字符扩展 ascii 共 16 种 由iso组织制定 从 ...
- WebAPI规范设计——违RESTful
本文首先简单介绍了几种API设计风格(RPC.REST.GraphQL),然后根据实现项目经验提出WebAPI规范设计思路,一些地方明显违反了RESTful风格,供大家参考! 一.几种设计风格介绍 1 ...
- 用.Net实现GraphRag:从零开始构建智能知识图谱
近来,大模型技术日新月异,使得与其相关的研发项目也层出不穷.其中一个备受关注的技术便是RAG(Retrieval Augmented Generation).今天,我要跟大家分享一个出色的项目:Gra ...
- ComfyUI插件:ComfyUI Impact 节点(一)
前言: 学习ComfyUI是一场持久战,而 ComfyUI Impact 是一个庞大的模块节点库,内置许多非常实用且强大的功能节点 ,例如检测器.细节强化器.预览桥.通配符.Hook.图片发送器.图片 ...
- AS上的基础中级控件-图形定制
图形Drawable 1.Drawable表达包含了图片色块画布背景等 2.存在res中的Drawable目录下,保存描述性的XML文件 3.各种视图都可以使用该控件如ViewText,Button, ...
- 登录到第一级终端后,如果再次ssh登录到其他终端,SecureCRT标签变更的问题
"终端->仿真->高级",勾选"忽略窗口标题更改请求"
- Gradle配置文件解析和使用Meven本地仓库
Gradle配置文件 使用Gradle创建好项目之后,项目的根目录下会有一个build.gradle文件,该文件就是Gradle的核心配置文件 对应的信息: plugins { id 'java' } ...
- 【Zookeeper】Re01 安装与操作
Zookeeper基于JDK开发出来的 运行环境至少需要JRE 快速安装JDK: yum install -y java-1.8.0-openjdk-devel.x86_64 # ZK镜像仓库 htt ...
- MindSpore社区的小礼物
前段时间在gitee上给MindSpore提过几个问题,后来一直没有回复,前几天得到了回复又通过网络视频聊了聊自己认为该开源项目还有哪些不足的地方,最后获赠了个小书包,对这个小礼物还是蛮喜欢的,下面给 ...
- [POI2015] MOD 题解
前言 题目链接:洛谷. 题意简述 给定一棵树,求断掉一条边再连上一条边所得的新树直径最小值和最大值,以及相应方案(你可以不进行任何操作,即断掉并连上同一条边). 题目分析 假设我们枚举断掉某一条边,得 ...