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教您玩转vim - 6 - # 保存修改
另存与保存 回忆上节课内容 我们上次进入了插入模式 从正常模式,按<kbd>i</kbd>,进插入模式 从插入模式,按<kbd>ctrl</kbd>+& ...
- oeasy教您玩转vim - 91 - # vim脚本编程展望
vim脚本编程展望 回忆 上次我们彻底研究了vim高亮的原理 各种语法项syntax item 关键字keyword 匹配模式match 区域region 定义好了之后还可以设置链接成组 hi d ...
- vscode取消json文件注释下划线
使用 vscode 打开一个json文件,如果有单行或多行注释,则会显示红色下划线,解决办法如下: 方法1 点击底部的JSON,选择 JSON with Comments 即可,然后红色下划线消失,底 ...
- JAVA私有构造函数---java笔记
在Java中,构造函数是一种特殊的方法,它用于初始化新创建的对象.当我们创建一个类的实例时,构造函数会自动被调用. 构造函数可以有不同的访问修饰符,如public.protected.default( ...
- Docker 使用Docker创建MySQL容器
使用Docker创建MySQL容器 实践环境 Docker version 20.10.5 MySQL5.7 Centos 7.8 创建步骤 1.拉取MySQL镜像 docker pull mysql ...
- html5 video标签 去掉边框黑线
只需在样式中添加: mix-blend-mode: darken; 注意:IE和Edge浏览器不支持mix-blend-mode属性
- pytest-req插件:更简单的做接口测试
pytest-req插件:更简单的做接口测试 背景 我们经常会用到 pytest 和 requests 进行接口自动化测试. pytest 提供了非常方便的插件开发能力,在pytest中使用reque ...
- RPA京麦咚咚批量发送消息
京麦咚咚发送消息,首先我们需要确定给谁发,发送什么内容 给谁发:可以传入京东用户名.京东订单号.咚咚将通过此条件进行搜索进入会话框 发送什么内容:批量发送信息给不同的用户,比如给不同的订单用户发送其相 ...
- 加油,为Vue3提供一个可媲美Angular的ioc容器
为什么要为Vue3提供ioc容器 Vue3因其出色的响应式系统,以及便利的功能特性,完全胜任大型业务系统的开发.但是,我们不仅要能做到,而且要做得更好.大型业务系统的关键就是解耦合,从而减缓shi山代 ...
- 【H5】16 表单 其五 表单验证
在将数据提交到服务器之前,重要的是确保以正确的格式填写所有必需的表单控件.这称为客户端表单验证,可帮助确保所提交的数据符合各种表单控件中规定的要求.本文将引导您通过基本概念和客户端表单验证示例. 先决 ...