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

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方法说明如下表:

序号参数名类型说明
1strbase64stringbase64数据
2outputFilenamestring输出的图像文件全路径

实现代码如下:

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 库&#xff0c;它可以把任意一个网页中的元素&#xff08;包括整个网页&#xff09;绘制到指定的 canvas 中&#xf…...

AI安全最佳实践:AI云原生开发安全评估矩阵(上)

保护生成式 AI&#xff1a;生成式 AI 安全范围矩阵简介 生成式人工智能&#xff08;生成式 AI&#xff09;正在吸引各大企业的关注&#xff0c;并在全球各行各业中重塑客户体验。这一 AI 能力的飞跃&#xff0c;由数十亿参数的大语言模型&#xff08;LLM&#xff09;和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-事务索引

一、事务-介绍 示例代码&#xff1a; 二、事务-四大特性 三、索引-介绍 无索引&#xff1a;全表扫描&#xff08;对应字段逐一比较&#xff09; 有索引&#xff1a;根据索引结构高效获取数据 优缺点&#xff1a; 四、索引-结构 五、索引-操作语法...

企业加密软件(天锐绿盾)

天锐绿盾是一款功能强大的企业加密软件&#xff0c;以下是对其的详细介绍&#xff1a; 一、产品概述 天锐绿盾&#xff08;又名绿盾信息安全管理软件&#xff09;&#xff0c;专注于企业数据防泄密&#xff0c;致力于为企业提供全方位的数据安全保障。其官网为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 实验结果验证 前言 在生产环境中&#xff0c;我们通常需要登录多个设备…...

如何抓取酒店列表: 揭开秘密

搜索酒店列表是一种强大的工具&#xff0c;可以从各种在线资源中收集有关住宿、价格和可用性的综合数据。无论您是要比较价格、分析市场趋势&#xff0c;还是要创建个性化的旅行计划&#xff0c;搜索都能让您有效地汇编所需的信息。在本文中&#xff0c;我们将介绍如何搜索酒店…...

day32-文件共享服务ftp与smb

文件共享服务方案有很多&#xff0c;了解即可 ftp&#xff08;简单文件传输服务&#xff09; 提供用户认证机制 可以输入账号密码 python -m SimpleHTTPServer nginx也提供了文件下载的功能 提供用户认证机制 反向代理&#xff0c;负载均衡 web服务器&#xff0c;静态文件…...

快速傅里叶离散变换FFT (更新中)

声明&#xff1a;参考了 y y c yyc yyc 的 blog 和 PPT (from smwc) &#xff0c;以及 w z r wzr wzr 的 blog 。 目录 Part 1 多项式Part 2 FFT概论Part 3 点值与插值Part 4 复数&#xff0c;单位根Part 5 Part 1 多项式 定义&#xff1a;对于有限数列 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​ 图片→格式→大小对话框→锁定纵横比✔动画→飞入→效果选项&#xff1a;方向/序列→开始→持续时间→延迟时间持续时间&#xff1a;1s延迟&#xff1a;0.5s音频剪切时间&#xff1a;0.5s&#xff1a;00:00.500自动换片时间设置&…...

企业百科和品牌百科创建技巧

很多人比较困惑&#xff0c;创建百科词条需要注意哪些事情&#xff1f;为什么参考提交了权威新闻参考资料还是没有通过&#xff0c;下面小马识途营销顾问就为大家解答疑惑&#xff1a; 1、品牌词以及企业词提交 1&#xff09;如果没有词条&#xff0c;我们可以通过平台提供的急…...

搭建集成开发环境PyCharm

1.下载安装Python&#xff08;建议下载并安装3.9.x&#xff09; https://www.python.org/downloads/windows/ 要注意勾选“Add Python 3.9 to PATH”复选框&#xff0c;表示将Python的路径增加到环境变量中 2.安装集成开发环境Pycharm http://www.jetbrains.com/pycharm/…...

【Rust自学】16.4. 通过Send和Sync trait来扩展并发

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 16.4.1. Send和Sync trait Rust语言本身的并发特性较少&#xff0c;目前所提及的并发特性都来自于标准库&#xff0c;而不是语言本身。其…...

2025年02月05日Github流行趋势

项目名称&#xff1a;OCRmyPDF 项目地址url&#xff1a;https://github.com/ocrmypdf/OCRmyPDF项目语言&#xff1a;Python历史star数&#xff1a;15872今日star数&#xff1a;157项目维护者&#xff1a;jbarlow83, fritz-hh, apps/dependabot, mawi12345, mara004项目简介&…...

拉取本地的 Docker 镜像的三种方法

方法 1&#xff1a;通过 docker save 和 docker load 导出和导入镜像 在本地服务器上导出镜像&#xff1a; 使用 docker save 将镜像保存为一个 .tar 文件&#xff1a; docker save -o mysql-5.7.tar mysql:5.7 将镜像文件传输到其他服务器&#xff1a; 你可以通过 scp 或其他…...

springboot+vue+uniapp的校园二手交易小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;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下部署(初级篇)

一、 前言&#xff1a; 其实早一个月我已经使用过deepseek&#xff0c;并且也在自己的机器上通过ollama部署过&#xff0c;但一直没有太多动力&#xff0c;现在感觉还是的记录一下&#xff0c;省的自己给忘掉了 本文只是简单记录一下ollamaopen-webuichatbox部署通过网盘分享…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...