React 实现PDF预览(数据源使用文件流而不是url)

一 前提

        应公司要求,需要进行上传文件(pdf)的预览功能,网上大部分都是使用url作为预览数据源,但是现在后端那边只返回了pdf文件流,所以本文主要是用文件流来预览pdf。

二  首先需要获取pdf文件流,并转化为base64格式的数据。

1. 封装axios方法,用于获取pdf文件流

const apiClient = axios.create({baseURL: '/', headers: {'Content-Type': 'application/json;charset=UTF-8'}
});// 封装的axiosget方法,获取pdf文件流 
const axiosGetFileBlob = async (url: string) => {try {const configs: any = {method: 'get',url: `${url}`,responseType: 'blob'};const res = await apiClient.get(url, configs);return res.data;} catch (error) {// 抛出异常信息}return null as any;
};

2.调用封装的方法,获取文件流并转为base64格式的数据。

 // 将文件流转为base64格式
const getBase64 = (file: any) => {return new Promise((resolve, reject) => {const reader = new FileReader();reader.readAsDataURL(file);reader.onload = () => resolve(reader.result);reader.onerror = error => reject(error);});
};  const getData = async () => {const res = await axiosGetFileBlob("这里是获取pdf的url");if (res) {// 这里获取到了文件流,首先需要转化为base64格式的数据const baseData = await getBase64(res);// 转化为base64的数据有一个文件类型的前缀,需要去掉。const resourceData = baseData.split(',')[1];// 这里需要拼接一个前缀,表示这个是一个pdf文件const finalData= "data:application/pdf;base64," + resourceData ;consloe.log("finalData就是获取到的pdf文件流");}}

 三 进行pdf预览功能

        根据第二步,可以拿到后端获取后并转化为base64格式的文件流数据。

        pdf预览有下列几种方式,主要分为系统自带预览(iframe,object,embed)以及插件预览(react-pdf-js)。大家可以自行选用合适。

1. 使用系统自带的方式预览(iframe,object,embed)。

        使用方式很简单,直接将第二步的finalData放到各自的数据源属性下。代码如下:

// 使用iframe
<iframe src={finalData+ "#toolbar=0"} height={800}>您的电脑不支持iframe</iframe>// 使用embed
<embed src={finalData+ "#toolbar=0"} height={800}/>// 使用 object
<object data={finalData+ "#toolbar=0"} height={800}></object>

效果如下:

 备注:

        预览的pdf大小自由设置标签的属性即可。

        #toolbar=0  代码的意思是隐藏顶部工具栏(下载、打印等),如果不加,则效果如下:

2.使用插件的方式预览(react-pdf-js)。

(1) 首先需要安装:

   yarn add @mikecousins/react-pdf  或者  npm install @mikecousins/react-pdf

(2)实现代码如下:

import React, {useEffect, useState} from "react";
import PDF from 'react-pdf-js';
// getFileBlob 就是上面提到过的:从后端拿取数据流
import {getFileBlob} from "@/services/common";
// getBase64 就是将数据转为base64格式
import {getBase64} from "@/utils/common";export default () => {const [totalPage, setTotalPages] = useState(1);const [currentPage, setCurrentPage] = useState(1);// 保存后端获取到后并转化为base64的数据流const [pdfBlob, setPdfBlob] = useState<any>(null);const getData = async () => {const res = await getFileBlob("20240902095451482799");debuggerif (res) {const baseData = await getBase64(res);const resourceData = baseData.split(',')[1];if (resourceData) {// 有数据再进行拼接,否则无效const finalData = "data:application/pdf;base64," + resourceData;setPdfBlob(finalData);}}}useEffect(() => {getData();});const onDocumentLoadSuccess = (totalPage: any) => {setTotalPages(totalPage);setCurrentPage(1);}// 一次展示所有界面const showAllPages = () => {const page = [];for (let i = 2; i <= totalPage; i++)page.push(<PDF page={i} key={`page-${i}`} file={finalPdfBlob} scale={1.5}/>);return page;}return (<div>{/* 一定要注意(必须要先进行pdfBlob的判定,pdfBlob 为空的话,不能继续下去。否则系统会报错。)*/}{pdfBlob && <div><PDFscale={1.5}file={pdfBlob}onDocumentComplete={onDocumentLoadSuccess}page={currentPage}/>{/* 一次性展示全部页面:代码如下 */}{totalPage > 1 && showAllPages()}{/*  这里也可以添加分页组件 ,进行分页展示,调用 setCurrentPage 即可。 */}</div>}</div>);
}

四 应用(在浏览器新打开的窗口中预览)

        我这里的预览使用的是iframe。将上面拿到的base64串,放到iframe中作为数据源。再结合window方法即可。代码如下:

<Button onClick={()=>getPdfContent("123456")}>预览<Button>  // 点击方法
const getPdfContent = async (id: string) => {try {// 从后端获取pdf数据流const pdfBlob = await getFileBlob(id);if (pdfBlob) {// 将pdf数据流转为base64字符串const pdfBase64 = await getBase64(pdfBlob);if (pdfBase64) {//获取的数据有前缀,不满足下载的pdf格式。需要去掉后,单独拼接pdf的格式const pdfData = pdfBase64.toString().split(',')[1]; const iframeSrc = `data:application/pdf;base64,${pdfData}`;// -----------------关键位置------------// 创建window.open方法,并将iframe结合数据源写入。const pdfWindow = window.open("", id);pdfWindow?.document.write(`<iframe width='100%' height='100%' src=${iframeSrc}></iframe>`);pdfWindow?.document.close();}}} catch (e) {console.log("系统错误!");}};

        

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/415468.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV绘图函数(15)图像上绘制矩形函数 rectangle()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 绘制一个简单的、粗的或填充的直立矩形。 这个函数 cv::rectangle 绘制一个矩形轮廓或一个填充的矩形&#xff0c;其两个相对的顶点分别是 pt1 和…

【STM32+HAL库】---- 按键中断控制LED

硬件开发板&#xff1a;STM32G0B1RET6 软件平台&#xff1a;cubemaxkeilVScode1 新建cubemax工程 1.1 配置系统时钟树 1.2 配置相关GPIO引脚 ①LED由PC13引脚控制 选择PA5引脚&#xff0c;GPIO_Output模式 GPIO模式配置&#xff1a; ②按键开关由PC13引脚控制 选择PC13引…

arcgisjs4.0 内网部署字体不显示问题处理

问题背景问题定位解决方案 问题背景 内网环境&#xff0c;通过压缩包的hash值验证了包是一摸一样的&#xff0c;ningx也读到了index.html&#xff0c;但是网格的字提显示出不来&#xff0c;并且地图上的注记文字均不显示 本地环境地图情况&#xff1a; 内网环境地图情况&…

Pepper佩盼尔wordpress模板

Pepper佩盼尔WordPress模板是一款专为追求简洁、现代和专业外观的网站设计者和开发者打造的高品质主题。它以简站为主题&#xff0c;强调“让建网站更简单”的理念&#xff0c;旨在为用户提供一个易于使用、功能丰富的平台来构建他们的在线业务或个人网站。 模板特点包括&…

AT+MQTT指令连接华为云实现数据上传

1 准备工作 硬件设备模块&#xff1a;ESP-01-S 固件烧录工具&#xff1a;ESP8266下载器 串口调试工具&#xff1a;VOFA参考文章&#xff1a;stm32AT指令ESP8266接入华为云物联网平台并完成属性上报与下发的命令处理 2 固件更新 2.1 为什么要重新安装固件 由于ESP-01-S模块出…

模拟算法专题——算法介绍算法讲解力扣实战应用

目录 1、模拟算法介绍 2、算法应用【leetcode】 2.1 替换所有的问号 2.1.1 算法思想 2.1.2 算法代码 2.2 提莫攻击 2.2.1 算法思想 2.2.2 算法代码 2.3 Z字形变换 2.3.1 算法思想 2.3.2 算法代码 2.4 外观数列 2.4.1 算法思想 2.4.2 算法代码 2.5 数青蛙 2.5.1 算…

计算机毕业设计选题推荐-博客平台-博客系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

【NLP自然语言处理】文本处理的基本方法

目录 &#x1f354;什么是分词 &#x1f354;中文分词工具jieba 2.1 jieba的基本特点 2.2 jieba的功能 2.3 jieba的安装及使用 &#x1f354;什么是命名实体识别 &#x1f354;什么是词性标注 &#x1f354;小结 学习目标 &#x1f340; 了解什么是分词, 词性标注, 命名…

解锁高效项目管理:精选软件项目管理工具与技术实战

在当今快节奏的商业环境中&#xff0c;项目管理不仅是确保任务按时完成的手段&#xff0c;更是企业战略规划与执行的核心。面对日益复杂的项目需求和不断变化的市场环境&#xff0c;传统的手工管理方式已难以满足高效协同的要求。此时&#xff0c;项目管理软件作为数字化时代的…

10款主流图纸加密软件大盘点|2024企业常用图纸加密软件分享(赶快码住!)

某天早上&#xff0c;小李&#xff0c;作为一家大型制造企业的设计工程师&#xff0c;正准备提交他耗时数月设计的一份机密产品图纸。就在点击发送的那一刻&#xff0c;突然发现网络异常。他的心猛地一沉&#xff0c;联想到前段时间公司内部的泄密事件&#xff0c;他不由得心跳…

yolov8目标检测pyside6可视化图形界面+检测源码ui文件——用于计数统计

项目结构 YOLOv8模型加载&#xff1a;加载预训练的YOLOv8模型。PySide6 GUI&#xff1a;设计图形用户界面&#xff0c;用于显示检测结果和控制选项。摄像头/视频输入&#xff1a;从摄像头或视频文件读取图像帧。目标检测&#xff1a;使用YOLOv8模型对输入图像进行实时目标检测…

中国水资源用水紧张程度数据(栅格/0.5度)

2010-2020年中国用水紧张程度栅格数据集 数据介绍 用水紧张程度被定义为淡水汲取量占可用淡水资源的比例&#xff0c;又称取水强度&#xff0c;是衡量可持续发展目标具体目标6.4进展状况的重要指标。本数据集为2010年至2020年中国用水紧张程度逐年数据&#xff0c;格式为Geoti…

Anylogic制作界面元素tips

点击元素后跳转至其他视图&#xff0c;且能够把某个共同元素移植过去 navigate( viewStatistics2 ); groupControls.setX( groupControls.getX() 1200 );

互联网全景消息(2)之RabbitMq高阶使用

一、RabbitMQ消息可靠性保障 消息的可靠性投递是使用消息中间件不可避免的问题&#xff0c;不管是Kafka、rocketMQ或者是rabbitMQ&#xff0c;那么在RabbitMQ中如何保障消息的可靠性呢&#xff1f; 首先来看一下rabbitMQ的 架构图&#xff1a; 首先从图里我们可以看到&#xff…

脑机接口定义及相关概念

1 什么是脑机接口 脑机接口(Brain-Computer Interface,简称,BCI)是指一种系统或设备,它通过解码大脑的电生理信号来与外部计算机或设备进行直接的通讯。BCI的目的是在不依赖身体运动的情况下实现大脑与计算机之间的信息交换。 2 相关概念 2.1 脑电图(EEG) 最常用的脑机接口技…

C# 窗口页面布局

1.Groupbox 单机鼠标右键&#xff0c;置于底层 2.Label 在右方属性中修改名称 3.ComboBox 点击属性中的集合&#xff0c;可以添加选择项 4.CheckBox 在属性中修改名称 5.RichTextBox 富文本 在属性中修改名称与区域 6.StatusStrip 状态栏 将AutoSize改成false就可以修改…

深入探索MySQL数据库结构设计:实战案例解析,打造高效、可扩展的数据存储方案

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 前言&#xff1a;…

vue-echarts :知识图谱可视化,动态更新 动态赋值series,更新options

<template><div style="display: flex;align-items: center;justify-content: space-between;"><

【大模型llms本质,并分析未来发展反向】

大模型的本质: 是有损压缩后的概率模型 2024年2月28日&#xff0c;OpenAI 的核心研发人员 Jack Rae 在参加 Stanford MLSys Seminar 的访谈时进行了一个名为 Compression for AGI 的主题分享&#xff0c;其核心观点为&#xff1a;AGI的一个关键目标是通过最小描述长度&#xf…

苹果11月推出新款M4 Mac:Mac mini设计焕新 MacBook Pro仅例行更新

据外媒 MacRumors 报道&#xff0c;苹果公司计划在 11 月推出首批 M4 Mac&#xff0c;这一时间表与去年相似&#xff0c;当时苹果公司在同样的时间点中宣布推出搭载 M3 芯片的 MacBook Pro。 ▲ 苹果公司在 2023 年 10 月 31 日推出的 M3 MacBook Pro 同时根据古尔曼爆料称苹果…