前端导出pdf,所见即所得

一、推荐方案:html2canvas + jsPDF(图片式PDF)

javascript

import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';const exportPDF = async (elementId, fileName) => {const element = document.getElementById(elementId);// 1. 将DOM转为Canvasconst canvas = await html2canvas(element, {scale: 2, // 提升清晰度useCORS: true, // 允许跨域图片logging: true, // 调试时开启});// 2. Canvas转图片数据const imgData = canvas.toDataURL('image/png', 1.0);// 3. 计算PDF尺寸const pdf = new jsPDF('p', 'mm', 'a4');const pageWidth = pdf.internal.pageSize.getWidth();const pageHeight = pdf.internal.pageSize.getHeight();const imgRatio = canvas.width / canvas.height;// 4. 自动适应页面大小let imgHeight = pageHeight;let imgWidth = pageWidth;if (pageWidth / imgRatio < pageHeight) {imgWidth = pageWidth;imgHeight = imgWidth / imgRatio;} else {imgHeight = pageHeight;imgWidth = imgHeight * imgRatio;}// 5. 添加图片到PDFpdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight);// 6. 保存文件pdf.save(`${fileName}.pdf`);
};// 使用示例
exportPDF('export-container', 'report');
 

二、进阶方案:jsPDF内置HTML渲染(矢量文本)

javascript

import { jsPDF } from "jspdf";const exportPDF = async () => {const doc = new jsPDF('p', 'pt', 'a4');// 1. 获取需要导出的HTML元素const element = document.getElementById('content');// 2. 直接渲染HTML到PDF(需要配合html2canvas)await doc.html(element, {callback: (doc) => doc.save('document.pdf'),margin: [20, 20, 20, 20],autoPaging: 'text',width: 170, // 有效内容区宽度(mm)windowWidth: element.scrollWidth,html2canvas: {scale: 0.5, // 控制分辨率letterRendering: true,},x: 10,y: 10,});
};

三、专业方案:Puppeteer(需后端配合)

javascript

// 前端
fetch('/generate-pdf', {method: 'POST',body: JSON.stringify({ html: document.documentElement.outerHTML }),headers: { 'Content-Type': 'application/json' }
});// Node.js后端
const puppeteer = require('puppeteer');app.post('/generate-pdf', async (req, res) => {const browser = await puppeteer.launch();const page = await browser.newPage();await page.setContent(req.body.html);const pdf = await page.pdf({ format: 'A4',printBackground: true });await browser.close();res.setHeader('Content-Type', 'application/pdf');res.send(pdf);
});

四、样式优化要点

  1. 打印样式表

css

@media print {@page { margin: 0; }body { -webkit-print-color-adjust: exact; }.no-print { display: none; }
}
  1. 强制分页

css

.page-break {page-break-after: always;break-after: page;
}
  1. 字体处理

css

@font-face {font-family: 'PDFFont';src: url('fonts/Songti.ttf') format('truetype');
}body {font-family: 'PDFFont', sans-serif;
}
 

五、方案对比

方案优点缺点
html2canvas+jsPDF纯前端实现,视觉保真度高文字变图片,文件体积较大
jsPDF HTML渲染支持矢量文字,自动分页兼容性问题,复杂布局易出错
Puppeteer完美还原,支持复杂CSS需要后端支持,消耗服务器资源
window.print()零依赖,简单快捷样式控制能力弱,交互体验差

六、常见问题处理

  1. 内容截断

javascript

// 手动计算分页位置
const elementHeight = element.offsetHeight;
const pageHeight = 1122; // A4像素高度(96dpi)
if (elementHeight > pageHeight) {// 插入分页符逻辑
}
  1. 图片跨域

html

​
<img crossorigin="anonymous" src="https://example.com/image.jpg">​

运行 HTML

  1. 提升清晰度

javascript

html2canvas(element, {scale: 3, // 最高3倍dpi: 300,letterRendering: true
});
 

根据具体需求选择方案:需要快速实现选择方案一,注重文字质量选方案二,企业级应用推荐方案三。

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

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

相关文章

【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter2-HTML 中的 JavaScript

二、HTML 中的 JavaScript 将 JavaScript 插入 HTML 的主要方法是使用<script>元素。 <script>元素有下列 8 个属性。 async&#xff1a;可选。表示应该立即开始下载脚本&#xff0c;但不能阻止其他页面动作&#xff0c;比如下载资源或等待其他脚本加载。只对外部…

数据分析系列--⑦RapidMiner模型评价(基于泰坦尼克号案例含数据集)

一、前提 二、模型评估 1.改造⑥ 2.Cross Validation算子说明 2.1Cross Validation 的作用 2.1.1 模型评估 2.1.2 减少过拟合 2.1.3 数据利用 2.2 Cross Validation 的工作原理 2.2.1 数据分割 2.2.2 迭代训练与测试 ​​​​​​​ 2.2.3 结果汇总 ​​​​​​​ …

Deepseek-v3 / Dify api接入飞书机器人go程序

准备工作 开通了接收消息权限的飞书机器人&#xff0c;例如我希望用户跟飞书机器人私聊&#xff0c;就需要开通这个权限&#xff1a;读取用户发给机器人的单聊消息 im:message.p2p_msg:readonly准备好飞书机器人的API key 和Secretdeepseek-v3的api keysecret&#xff1a;http…

电话号码的字母组合(力扣17)

这道题注意两个点。一是根据题目所给的键盘布局进行数字到英文字符串的映射&#xff0c;这一步可以用二维数组实现。二是这道题在递归的时候不需要缩小范围&#xff0c;这与之前写的组合题目有所不同。此题并不是在一个集合中不断递归遍历&#xff0c;而是递归另一个集合&#…

红黑树原理及C语言实现

目录 一、原理 二、操作示例 三、应用场景 四、C语言实现红黑树 五、代码说明 六、红黑树和AVL树对比 一、原理 熟悉红黑树之前&#xff0c;我们需要了解二叉树与二叉查找树概念&#xff0c;参见前述相关文章&#xff1a;二叉查找树BST详解及其C语言实现-CSDN博客 红黑…

DeepSeek V2报告阅读

概况 MoE架构&#xff0c;236B参数&#xff0c;每个token激活参数21B&#xff0c;支持128K上下文。采用了包括多头潜在注意力&#xff08;MLA&#xff09;和DeepSeekMoE在内的创新架构。MLA通过将KV缓存显著压缩成潜在向量来保证高效的推理&#xff0c;而DeepSeekMoE通过稀疏计…

TCP服务器与客户端搭建

一、思维导图 二、给代码添加链表 【server.c】 #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <fcntl.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.…

【自动化测试】使用Python selenium类库模拟手人工操作网页

使用Python selenium类库模拟手人工操作网页 背景准备工作安装Python版本安装selenium类库下载selenium驱动配置本地环境变量 自动化脚本输出页面表单自动化填充相关代码 背景 待操作网页必须使用IE浏览器登录访问用户本地只有edge浏览器&#xff0c;通过edge浏览器IE模式访问…

如何通过Davinci Configurator来新增一个BswM仲裁规则

本文框架 前言1.增加一个Mode Declaration Group2.增加一个Mode Request RPorts3.与操作Port的SWC连线4.新建一个Expression5.新建ActionList6.将表达式新建或加进现有Rule内7.生成BswM及Rte模块代码8.在代码中调用RTE接口前言 在Autosar模式管理系列介绍01-BswM文章中,我们对…

智慧交通:如何通过数据可视化提升城市交通效率

随着城市化进程的加速&#xff0c;交通管理面临着前所未有的挑战。为了应对日益复杂的交通状况&#xff0c;智慧交通系统应运而生&#xff0c;其中数据可视化技术成为了提升交通管理效率的关键一环。本文将探讨如何利用山海鲸可视化软件来优化交通管理&#xff0c;并展示其在智…

Android Studio:如何利用Application操作全局变量

目录 一、全局变量是什么 二、如何把输入的信息存储到全局变量 2.1 MainApplication类 2.2 XML文件 三、全局变量读取 四、修改manifest ​编辑 五、效果展示 一、全局变量是什么 全局变量是指在程序的整个生命周期内都可访问的变量&#xff0c;它的作用范围不限于某个…

DeepSeek模型构建与训练

在完成数据预处理之后,下一步就是构建和训练深度学习模型。DeepSeek提供了简洁而强大的API,使得模型构建和训练变得非常直观。无论是简单的全连接网络,还是复杂的卷积神经网络(CNN)或循环神经网络(RNN),DeepSeek都能轻松应对。本文将带你一步步构建一个深度学习模型,并…

Chrome 浏览器 支持多账号登录和管理的浏览器容器解决方案

根据搜索结果&#xff0c;目前没有直接提到名为“chrometable”的浏览器容器或插件。不过&#xff0c;从功能描述来看&#xff0c;您可能需要的是一个能够支持多账号登录和管理的浏览器容器解决方案。以下是一些可能的实现方式&#xff1a; 1. 使用 Docker 容器化部署 Chrome …

UdpServer

Udp服务端&#xff1a; using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; using System.IO; using …

Kafka 可靠性探究—副本刨析

Kafka 的多副本机制提升了数据容灾能力。 副本通常分为数据副本与服务副本。数据副本是指在不同的节点上持久化同一份数据&#xff1b;服务副本指多个节点提供同样的服务&#xff0c;每个节点都有能力接收来自外部的请求并进行相应的处理。 1 副本刨析 1.1 相关概念 AR&…

智能化转型2.0:从“工具应用”到“价值重构”

过去几年&#xff0c;“智能化”从一个模糊的概念逐渐成为企业发展的核心议题。2024年&#xff0c;随着生成式AI、大模型、智能体等技术的爆发式落地&#xff0c;中国企业正式迈入智能化转型的2.0时代。这一阶段的核心特征是从单一场景的“工具应用”转向全链条的“价值重构”&…

Unity Dots学习

ISystem和SystemBase的区别 Archetype和Chunk 相同组件的实体放在一起&#xff0c;也就是我们所说的内存块&#xff08;Chunk&#xff09; Chunk有一个大小 https://blog.csdn.net/weixin_40124181/article/details/103716338 如果批量操作的entity都是同一个chunk下的效率会更…

【1】高并发导出场景下,服务器性能瓶颈优化

高并发导出场景下&#xff0c;服务器性能瓶颈通常出现在 CPU、内存、磁盘 I/O 或网络带宽等方面。为了解决这些问题&#xff0c;可以从以下几个方面进行优化&#xff1a; 1. 优化导出逻辑 减少计算复杂度&#xff1a;检查导出逻辑中是否存在不必要的计算或重复操作&#xff0c;…

使用 Axios 获取用户数据并渲染——个人信息设置

目录 1. HTML 部分&#xff08;前端页面结构&#xff09; HTML 结构解析&#xff1a; 2. JavaScript 部分&#xff08;信息渲染逻辑&#xff09; JavaScript 解析&#xff1a; 3. 完整流程 4. 总结 5. 适用场景 本文将介绍如何通过 Axios 从服务器获取用户信息&#xff0…

能否通过蓝牙建立TCP/IP连接来传输数据

前言&#xff1a; 最近在做一个项目时&#xff0c;产生了一个疑问&#xff1a;能否通过蓝牙建立TCP/IP连接来传输数据 查阅了一些文章&#xff0c;可以得出结论&#xff1a;不行 下面是我截取的两篇个人认可的文章的回答&#xff1a; 文章一&#xff1a; 蓝牙是一种短距离无…