C#结合html2canvas生成切割图片并导出到PDF
目录
需求
开发运行环境
实现
生成HTML范例片断
HTML元素转BASE64
BASE64转图片
切割长图片
生成PDF文件
小结
需求
html2canvas 是一个 JavaScript 库,它可以把任意一个网页中的元素(包括整个网页)绘制到指定的 canvas 中,适用于生成网截图或将指定元素容器内容保存为图像等。现有需求如下:
1、C#后台输出HTML片段内容到客户端;
2、引入 html2canvas 库,放置 canvas 对象,操作客户端功能保存 canvas 内容生成图像 base64数据;
3、回传 base64 数据,C# 生成图像
4、C# 对于生成的长图进行切割,生成多张图片
5、将多张图片导出生成到PDF文件。
开发运行环境
操作系统: Windows Server 2019 DataCenter
.net版本: .netFramework4.7.2
js库:html2canvas 1.3.2 版本库
数据库:MS SQL SERVER 2016
开发工具:VS2019 C#
实现
生成HTML范例片断
我们假设有存储过程(CCDN_getTableDetail),通过传递表名参数(@tablename nvarchar(50)),可以获取表的详细信息,包括(表名、表说明、字段序号、字段名、字段说明、标识、主键、类型、长度、占用字节数、小数位数、允许空、默认值),代码如下:
CREATE PROCEDURE CCDN_getTableDetail @tablename nvarchar(50)
AS
BEGIN-- SET NOCOUNT ON added to prevent extra result sets from-- interfering with SELECT statements.SET NOCOUNT ON;
SELECT表名=convert(nvarchar(50),case when a.colorder=1 then d.name else '' end),表说明=convert(nvarchar(50),case when a.colorder=1 then isnull(f.value,'') else '' end),字段序号=convert(nvarchar(50),a.colorder),字段名=convert(nvarchar(50),a.name),字段说明=convert(nvarchar(50),isnull(g.[value],'')),标识=convert(nvarchar(50),case when COLUMNPROPERTY(a.id,a.name,'IsIdentity')=1 then '√'else '' end),主键=convert(nvarchar(50),case when exists(SELECT 1 FROM sysobjects where xtype='PK' and name in (SELECT name FROM sysindexes WHERE indid in(SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid))) then '√' else '' end),类型=convert(nvarchar(50),b.name),长度=convert(nvarchar(50),COLUMNPROPERTY(a.id,a.name,'PRECISION')),占用字节数=convert(nvarchar(50),a.length),小数位数=convert(nvarchar(50),isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0)),允许空=convert(nvarchar(50),case when a.isnullable=1 then 'NULL'else 'NOT NULL' end),默认值=convert(nvarchar(50),isnull(e.text,''))FROM syscolumns aleft join systypes b on a.xtype=b.xusertypeinner join sysobjects d on a.id=d.id and d.xtype='U' and d.name<>'dtproperties'left join syscomments e on a.cdefault=e.idleft join sys.extended_properties g on a.id=g.major_id and a.colid=g.minor_idleft join sys.extended_properties f on d.id=f.major_id and f.minor_id =0where d.name=@tablenameorder by a.id,a.colorder
END
运行效果如下图:

现我们通过 DataSet 获取数据集数据,并绑定显示在 DataGrid 控件(q_dbgrid)上。 如何获取数据集信息可阅读我的文章《C# 利用IDbDataAdapter / IDataReader 实现通用数据集获取》。
绑定示例代码如下:
object rv2 = GetDataSet(sql, paras,CommandType.StoredProcedure);DataSet ds = (DataSet)rv2;DataTable dt = ds.Tables[0];q_dbgrid.AllowPaging = true;q_dbgrid.PagerStyle.Visible = false;q_dbgrid.PageSize = 1000;q_dbgrid.DataSource = ds;q_dbgrid.DataBind();
HTML元素转BASE64
在页面上放置 canvas 画布控件(myCanvas)和临时存放BASE64数据的 TextBox 控件(ds),首先需要引用 html2canvas js库,如下:
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.3.2/html2canvas.min.js"></script>
客户端示例代码如下:
<script language="javascript" type="text/javascript">window.onload = function () {var canvas = document.getElementById("myCanvas")html2canvas(document.getElementById("q_dbgrid")).then(canvas => {document.getElementById("myCanvas").appendChild(canvas); // 将生成的canvas添加到页面上var image = canvas.toDataURL("image/jpeg");document.getElementById("ds").value = image;});}
</script>
通过 html2canvas 方法生成 jpeg类型的图像数据(canvas.toDataURL("image/jpeg"))并存储在 ds 控件里。
BASE64转图片
Base64StringToImage方法说明如下表:
| 序号 | 参数名 | 类型 | 说明 |
|---|---|---|---|
| 1 | strbase64 | string | base64数据 |
| 2 | outputFilename | string | 输出的图像文件全路径 |
实现代码如下:
public bool Base64StringToImage(string strbase64, string outputFilename)
{byte[] arr = Convert.FromBase64String(strbase64);MemoryStream ms = new MemoryStream(arr);System.Drawing.Image img = System.Drawing.Image.FromStream(ms);img.Save(outputFilename);img.Dispose();if (File.Exists(outputFilename)){return true;}return false;
}
切割长图片
为保证较好的显示效果,可能需要对长图片进行切割,生成多个图像文件,并存到指定的目录里,以备后续导出生成PDF文件使用。示例代码如下:
string outjpgpath = "D:\\testPDF\\";
string filename="D:\\test.jpg";
string base64Data = ds.Text.Trim().Replace("data:image/jpeg;base64,", "");
Base64StringToImage(base64Data, filename);System.Drawing.Bitmap sbitmap = new System.Drawing.Bitmap(filename);
int out_width = sbitmap.Width;
int ref_height = 1000; int com_height = sbitmap.Height;
int hCount =sbitmap.Height<ref_height?1:sbitmap.Height % ref_height==0?sbitmap.Height/ref_height:sbitmap.Height/ref_height+1;
int out_top = 0;
int out_height = ref_height;for (int i = 1; i <= hCount; i++)
{if (i == 1) { out_top = 0; } else { out_top = ref_height * (i - 1) + 1; }out_height = com_height < ref_height ? System.Math.Abs(com_height)-1 : ref_height;com_height -= ref_height;System.Drawing.Bitmap dbitmap = sbitmap.Clone(new System.Drawing.RectangleF(0, out_top, sbitmap.Width, out_height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);string f = "test" + ("0000" + i.ToString()).PadLeft(4) + ".jpg";dbitmap.Save(outjpgpath + f);dbitmap.Dispose();
}
sbitmap.Dispose();
outjpgpath为输出的多图片目录,filename 为生成的长图的地址。
ref_height为自定义的切割高度,根据指定切割高底生成若干“子”图片。
生成PDF文件
通过读取目录中的多个图像文件生成PDF,可阅读我的文章《C# 将批量图片转为PDF文件》,这里不再赘述。
小结
切割图片中的 ref_height,我们可以根据自定义的要求进行设定,如某些标准的页面尺寸像素值。另外,一些异常情况也需要进行判断,图片的生成质量也可以进行调整 ,这些我们都要根据实际的应用进行调整。
另外,还可以通过API的方式,将网页内容保存为图片,循环生成对应的图片,以解决长图片切割的问题,可参阅我的文章《C# 实现网页内容保存为图片并生成压缩包》
感谢您的阅读,希望本文能够对您有所帮助。
相关文章:
C#结合html2canvas生成切割图片并导出到PDF
目录 需求 开发运行环境 实现 生成HTML范例片断 HTML元素转BASE64 BASE64转图片 切割长图片 生成PDF文件 小结 需求 html2canvas 是一个 JavaScript 库,它可以把任意一个网页中的元素(包括整个网页)绘制到指定的 canvas 中…...
AI安全最佳实践:AI云原生开发安全评估矩阵(上)
保护生成式 AI:生成式 AI 安全范围矩阵简介 生成式人工智能(生成式 AI)正在吸引各大企业的关注,并在全球各行各业中重塑客户体验。这一 AI 能力的飞跃,由数十亿参数的大语言模型(LLM)和Transfo…...
[ Spring ] Spring Boot Mybatis++ 2025
文章目录 StructureMyBatis Controller AbilitiesConfigure Plugins and RepositoriesApply Plugins and Add DependenciesMyBatis Spring PropertiesMyBatis ApplicationMyBatis BeansMyBatis MapperMyBatis Query Builder Structure this blog introduce 3 ways using mybat…...
JAVAweb学习日记(九) MySQL-事务索引
一、事务-介绍 示例代码: 二、事务-四大特性 三、索引-介绍 无索引:全表扫描(对应字段逐一比较) 有索引:根据索引结构高效获取数据 优缺点: 四、索引-结构 五、索引-操作语法...
企业加密软件(天锐绿盾)
天锐绿盾是一款功能强大的企业加密软件,以下是对其的详细介绍: 一、产品概述 天锐绿盾(又名绿盾信息安全管理软件),专注于企业数据防泄密,致力于为企业提供全方位的数据安全保障。其官网为www.drhchina.c…...
Python实现监督学习与无监督学习
在机器学习中,算法被广泛应用于解决实际问题。监督学习与无监督学习是其中两种重要的学习范式。监督学习通过已标注的数据进行训练,目标是学会预测未知数据的标签。而无监督学习不需要数据的标签,它专注于数据的结构和模式,通常用于聚类或降维等任务。 本教程的目标是帮助…...
Python网络自动化运维---批量登录设备
文章目录 目录 文章目录 前言 实验准备 一.批量登录 IP 连续的设备 1.1.1 实验代码 1.1.2 代码分段分解 1.1.3 实验结果验证 二.批量登录 IP 不连续的设备 2.2.1 实验代码 2.2.2 代码分段分解 2.2.3 实验结果验证 前言 在生产环境中,我们通常需要登录多个设备…...
如何抓取酒店列表: 揭开秘密
搜索酒店列表是一种强大的工具,可以从各种在线资源中收集有关住宿、价格和可用性的综合数据。无论您是要比较价格、分析市场趋势,还是要创建个性化的旅行计划,搜索都能让您有效地汇编所需的信息。在本文中,我们将介绍如何搜索酒店…...
day32-文件共享服务ftp与smb
文件共享服务方案有很多,了解即可 ftp(简单文件传输服务) 提供用户认证机制 可以输入账号密码 python -m SimpleHTTPServer nginx也提供了文件下载的功能 提供用户认证机制 反向代理,负载均衡 web服务器,静态文件…...
快速傅里叶离散变换FFT (更新中)
声明:参考了 y y c yyc yyc 的 blog 和 PPT (from smwc) ,以及 w z r wzr wzr 的 blog 。 目录 Part 1 多项式Part 2 FFT概论Part 3 点值与插值Part 4 复数,单位根Part 5 Part 1 多项式 定义:对于有限数列 A 0 A_{0} A0~ n…...
【从零开始入门unity游戏开发之——C#篇48】C#补充知识点——静态导入、异常捕获和异常筛选器、nameof运算符
考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…...
8.PPT:小李-第二次世界大战【21】
目录 NO123 NO4567 NO8\9\10\11 图片→格式→大小对话框→锁定纵横比✔动画→飞入→效果选项:方向/序列→开始→持续时间→延迟时间持续时间:1s延迟:0.5s音频剪切时间:0.5s:00:00.500自动换片时间设置&…...
企业百科和品牌百科创建技巧
很多人比较困惑,创建百科词条需要注意哪些事情?为什么参考提交了权威新闻参考资料还是没有通过,下面小马识途营销顾问就为大家解答疑惑: 1、品牌词以及企业词提交 1)如果没有词条,我们可以通过平台提供的急…...
搭建集成开发环境PyCharm
1.下载安装Python(建议下载并安装3.9.x) https://www.python.org/downloads/windows/ 要注意勾选“Add Python 3.9 to PATH”复选框,表示将Python的路径增加到环境变量中 2.安装集成开发环境Pycharm http://www.jetbrains.com/pycharm/…...
【Rust自学】16.4. 通过Send和Sync trait来扩展并发
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 16.4.1. Send和Sync trait Rust语言本身的并发特性较少,目前所提及的并发特性都来自于标准库,而不是语言本身。其…...
2025年02月05日Github流行趋势
项目名称:OCRmyPDF 项目地址url:https://github.com/ocrmypdf/OCRmyPDF项目语言:Python历史star数:15872今日star数:157项目维护者:jbarlow83, fritz-hh, apps/dependabot, mawi12345, mara004项目简介&…...
拉取本地的 Docker 镜像的三种方法
方法 1:通过 docker save 和 docker load 导出和导入镜像 在本地服务器上导出镜像: 使用 docker save 将镜像保存为一个 .tar 文件: docker save -o mysql-5.7.tar mysql:5.7 将镜像文件传输到其他服务器: 你可以通过 scp 或其他…...
springboot+vue+uniapp的校园二手交易小程序
开发语言:Java框架:springbootuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包&#…...
NeetCode刷题第21天(2025.2.4)
文章目录 114 Gas Station 加油站115 Hand of Straights 顺子之手116 Merge Triplets to Form Target 将 Triplelet 合并到 Form Target117 Partition Labels 分区标签118 Valid Parenthesis String 有效的括号字符串119 Insert Interval 插入间隔120 Merge Intervals 合并区间…...
人工智能|本地部署|ollama+chatbox快速Windows10下部署(初级篇)
一、 前言: 其实早一个月我已经使用过deepseek,并且也在自己的机器上通过ollama部署过,但一直没有太多动力,现在感觉还是的记录一下,省的自己给忘掉了 本文只是简单记录一下ollamaopen-webuichatbox部署通过网盘分享…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...
