当前位置: 首页 > news >正文

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF,同时需要下载、打印的需求,通常由于浏览器的安全策略,可以预览,但是下载和打印可能会受限,这时候怎么办呢?

1.创建一个隐藏的标签

要下载 iframe 中的 PDF 文件,你可以通过以下步骤实现:

  1. 获取 PDF 文件的 URL:确保你已经有一个指向 PDF 文件的 URL,即 url
  2. 创建一个下载链接:使用 JavaScript 创建一个隐藏的下载链接,并触发点击事件来下载文件。

以下是一个示例代码:

// 假设 url是你已经定义的 PDF 文件 URL
const downloadPdf = () => {const link = document.createElement('a');link.href = url;link.download = 'document.pdf'; // 你可以根据需要更改文件名document.body.appendChild(link);link.click();document.body.removeChild(link);
};// 在你的组件中添加一个按钮来触发下载
<button onClick={downloadPdf}>下载 PDF</button>

将上述代码集成到你的 index.jsx 文件中,确保 slnPdfUrl 是有效的 PDF 文件 URL。用户点击按钮时,PDF 文件将被下载。

示例集成

假设你的 index.jsx 文件如下:

import React from 'react';const YourComponent = ({ slnPdfUrl }) => {const downloadPdf = () => {const link = document.createElement('a');link.href = slnPdfUrl;link.download = 'document.pdf';document.body.appendChild(link);link.click();document.body.removeChild(link);};return (<div><iframe className='sln-detail-pdf'src={slnPdfUrl}width="100%" height="100%"/><button onClick={downloadPdf}>下载 PDF</button></div>);
};export default YourComponent;

但是呢,有些浏览器会直接打开一个新窗口显示pdf,并没有下载PDF

2. Fetch方式

上面的问题通常是由于以下几个原因造成的:

  1. 浏览器行为

    • 某些浏览器可能不会自动下载文件,而是会在新标签页中打开文件。这取决于浏览器的设置和文件类型。
  2. 文件 URL 的问题

    • 确保 url 是一个有效的 URL,并且指向一个可以直接下载的文件资源。
  3. CORS 问题

    • 如果 url 是一个跨域的 URL,浏览器可能会阻止下载操作,除非服务器正确设置了 CORS 头。
  4. 文件 MIME 类型

    • 确保服务器返回的文件具有正确的 MIME 类型(例如,PDF 文件应为 application/pdf),以确保浏览器能够正确处理下载。

解决方法

1. 检查文件 URL

确保 url 是一个有效的 URL,并且指向一个可以直接下载的文件资源。你可以在浏览器中直接访问该 URL,看看是否能正常下载文件。

2. 检查 CORS 设置

如果 url 是一个跨域的 URL,确保服务器设置了正确的 CORS 头。例如,服务器应该返回以下头信息:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type
3. 检查文件 MIME 类型

确保服务器返回的文件具有正确的 MIME 类型。例如,对于 PDF 文件,服务器应该返回 Content-Type: application/pdf

4. 使用 fetchaxios 下载文件

如果上述方法都不奏效,可以尝试使用 fetchaxios 来下载文件。以下是一个使用 fetch 的示例:

const slnDownload = async () => {if (!url) {message.error('PDF URL 无效');return;}try {const response = await fetch(url);if (!response.ok) {throw new Error('网络响应不正确');}const blob = await response.blob();const url = window.URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = 'document.pdf';document.body.appendChild(a);a.click();a.remove();window.URL.revokeObjectURL(url);} catch (error) {message.error('下载文件时出错: ' + error.message);}
};

示例代码解释

  1. 检查 URL

    • 确保 url 存在且有效。
  2. 使用 fetch 获取文件

    • 使用 fetch 发送请求以获取文件的二进制数据(blob)。
  3. 创建下载链接

    • 创建一个临时的 URL 对象(URL.createObjectURL)。
    • 创建一个隐藏的 <a> 标签,并设置其 hrefdownload 属性。
    • 触发点击事件以开始下载。
    • 移除临时的 <a> 标签并释放 URL 对象。

3.组件化

笔者直接提供一个react的PDF组件,可以直接复制到自己工程里使用。

工程结构

在这里插入图片描述

index.jsx代码

import React, { useRef, useEffect, useState } from 'react';
import { Button,  message} from "antd";
import './index.less';
export default function RPdf(props, ref) {const [url, setUrl] = useState('');const iframeRef = useRef(null);useEffect(() => {init();}, [props.src,props.download])const init = async() => {if (!props.src) {return;}try {const pdfResponse = await fetch(props.src);if (!pdfResponse.ok) {throw new Error('网络响应不正确');}const blob = await pdfResponse.blob();const url = window.URL.createObjectURL(blob);setUrl(url);} catch (error) {message.error('加载 PDF 时出错: ' + error.message);}}const downloadPdf = async() => {if (!url) {message.error('PDF URL 无效');return;}try {const a = document.createElement('a');a.href = url;a.download = props.download;document.body.appendChild(a);a.click();a.remove();window.URL.revokeObjectURL(url);} catch (error) {message.error('下载文件时出错: ' + error.message);}}const printPdf = () => {if (!url) {message.error('PDF URL 无效');return;}const iframe = iframeRef.current;if (!iframe) {message.error('无法找到 iframe');return;}iframe.contentWindow.focus();iframe.contentWindow.print();}return (<div className='r-pdf-container'><div className='r-pdf-header'><Button onClick={downloadPdf}>下载</Button><Button onClick={printPdf}>打印</Button></div><div className="r-pdf-content"><iframe className='r-pdf'ref={iframeRef}src={url}width="100%" height="100%"/></div></div>)
}

index.less代码

.r-pdf-container {width: 100%;height: 100%;display: flex;flex-direction: column;gap: 6px;margin: 12px;.r-pdf-header {height: 40px;display: flex;justify-content: flex-end;gap: 8px;}.r-pdf-content {width: 100%;height: 100%;// overflow: auto;.r-pdf {border: 0px;}}
}

使用

<RPdf src={url} download={yourDownloadName+'.pdf'} />

相关文章:

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF&#xff0c;同时需要下载、打印的需求&#xff0c;通常由于浏览器的安全策略&#xff0c;可以预览&#xff0c;但是下载和打印可能会受限&#xff0c;这时候怎么办呢&#xff1f; 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件&#xff0c;…...

git clone ssh 设置代理

Linux配置方法 编辑 ~/.ssh/config 文件 Host github.com Hostname github.com ProxyCommand nc -v -x 127.0.0.1:1080 %h %pwindows配置方法 编辑 C:\Users\当前用户名.ssh\config 文件 Host github.com Hostname github.com ProxyCommand connect -S 127.0.0.1:1080 %h %…...

RK3568平台(USB篇)USB网络共享

使用RK的USB网络共享,在内核里面已经有了,这不需要自己写驱动程序,只需要把内核自带的USB网络共享的驱动添加上去即可。 一.RNDIS 协议简介 RNDIS 是微软定义的一种协议,它允许通过 USB 接口实现网络连接。通过 RNDIS,USB 设备可以充当网络适配器,允许主机通过 USB 与设…...

vite 打包时:JavaScript heap out of memory(内存溢出)

出错原因分析&#xff1a; 执行命令 npm run build 时出现以下错误提示&#xff1a; vite v3.2.7 building for production... 11:22:34 transforming (3) src\main.tsWARN Browserslist: caniuse…...

【服务器学习专栏 1.2 -- 带外管理】

请阅读 嵌入式学习必备专栏 文章目录 Overview服务器带外管理BMC 介绍BMC 特点BMC 工作原理 Overview 从技术的角度&#xff0c;网络管理可分为带外管理&#xff08;out-of-band&#xff09;和带内管理&#xff08;in-band&#xff09;两种管理模式。 带内管理&#xff0c;是指…...

微服务のGeteWay

目录 概念&#xff1a; 三大核心&#xff1a; 工作流程&#xff1a; 9527网关如何做路由映射&#xff1a; GetWay高级特性&#xff1a; 按服务名动态路由服务&#xff1a; 断言Route Predicate Factories &#xff1a; 获取当前时区时间&#xff1a; After Route &…...

html+css+js网页设计 美食 美食家6个页面

htmlcssjs网页设计 美食 美食家6个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xf…...

IntelliJ Idea常用快捷键详解

文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中&#xff…...

服务器虚拟化:它是什么以及有什么好处?

运行虚拟服务器有助于创建更高效的 IT 基础架构。 随着业务每天收集的数据量逐年激增&#xff0c;传统的物理服务器已经无法单独满足业务需求。 相反&#xff0c;许多组织正在转向虚拟化的力量。 这是我们创建物理实体的虚拟版本的过程&#xff0c;在计算中&#xff0c;通常指…...

Python爬虫完整代码拿走不谢

对于新手做Python爬虫来说是有点难处的&#xff0c;前期练习的时候可以直接套用模板&#xff0c;这样省时省力还很方便。 使用Python爬取某网站的相关数据&#xff0c;并保存到同目录下Excel。 直接上代码&#xff1a; import re import urllib.error import urllib.request…...

MLA:多头潜在注意力

MLA:多头潜在注意力 多头潜在注意力(MLA)机制是一种在深度学习模型中用于处理序列数据的注意力机制的改进形式,以下是对其原理和示例的详细介绍: 原理 低秩键值联合压缩:MLA机制利用低秩键值联合压缩来消除注意力模块中的某些计算,从而提高模型的运行速度和性能。在传…...

阿里云大模型ACP高级工程师认证模拟试题

阿里云大模型ACP高级工程师认证模拟试题 0. 引言1. 模拟试题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题单选题单选题多选题多选题单选题多选题单…...

游戏引擎学习第67天

reviewing “apron”概念以更新区域 我们正在进行模拟区域的扩展工作&#xff0c;目标是通过增加一个更大的区域来支持更丰富的互动&#xff0c;尤其是那些可能超出摄像机视野的内容。现有的模拟区域包括摄像机能看到的区域和其周围的环境区域&#xff0c;但为了保证更高效的游…...

Nginx知识详解(理论+实战更易懂)

目录 一、Nginx架构和安装 1.1 Nginx 概述 1.1.1 nginx介绍 1.1.2?Nginx 功能介绍 1.1.3?基础特性 1.1.4?Web 服务相关的功能 1.2?Nginx 架构和进程 1.2.1?Nginx 进程结构 1.2.2?Nginx 进程间通信 1.2.3?Nginx 启动和 HTTP 连接建立 1.2.4?HTTP 处理过程 1…...

# 【鸿蒙开发】多线程之Worker的使用

【鸿蒙开发】多线程之Worker的使用 文章目录 【鸿蒙开发】多线程之Worker的使用前言一、Worker的介绍二、注意事项三、Worker使用示例1.新建一个Worker2.主线程使用Worker3.子线程Worker的使用 四、效果展示 前言 本文主要介绍了多线程的方法之一&#xff0c;使用Worker开启多…...

TKG-DM – 基于Latent Diffusion模型的“原生”色度提取生成具有透明通道的图像

概述 原文地址&#xff1a;https://www.unite.ai/improving-green-screen-generation-for-stable-diffusion/ 论文地址&#xff1a;https://arxiv.org/pdf/2411.15580 尽管社区研究和投资者对图像生成人工智能充满热情&#xff0c;但此类系统的输出并不总是可以直接用于产品开…...

告别 Windows 迟缓!多维度优化策略开启流畅新体验

在日常使用 Windows 系统的过程中&#xff0c;随着时间推移和软件安装卸载&#xff0c;系统可能会出现运行缓慢、卡顿等问题。本文中简鹿办公将详细介绍一系列 Windows 系统优化方法&#xff0c;涵盖多个关键层面&#xff0c;助力您的电脑重焕生机。 一、磁盘清理与优化 磁盘…...

亚马逊国际站商品爬虫:Python实战指南

在数字化时代&#xff0c;数据的价值不言而喻。对于电商领域而言&#xff0c;获取竞争对手的商品信息、价格、评价等数据&#xff0c;对于市场分析和策略制定至关重要。本文将带你了解如何使用Python编写爬虫&#xff0c;以亚马逊国际站为例&#xff0c;按照关键字搜索并获取商…...

RabbitMQ基础篇之Java客户端快速入门

文章目录 需求 项目设置与依赖管理 配置RabbitMQ的连接信息创建队列与消息发送创建消费者&#xff08;消息接收&#xff09;环境准备与操作 需求 利用控制台创建队列 simple.queue在 publisher 服务中&#xff0c;利用 SpringAMQP 直接向 simple.queue 发送消息在 consumer 服…...

深度学习:基于MindSpore NLP的数据并行训练

什么是数据并行&#xff1f; 数据并行&#xff08;Data Parallelism, DP&#xff09;的核心思想是将大规模的数据集分割成若干个较小的数据子集&#xff0c;并将这些子集分配到不同的 NPU 计算节点上&#xff0c;每个节点运行相同的模型副本&#xff0c;但处理不同的数据子集。…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

JDK 17 序列化是怎么回事

如何序列化&#xff1f;其实很简单&#xff0c;就是根据每个类型&#xff0c;用工厂类调用。逐个完成。 没什么漂亮的代码&#xff0c;只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...

Selenium 查找页面元素的方式

Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素&#xff0c;以下是主要的定位方式&#xff1a; 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...