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

C# 实现网页内容保存为图片并生成压缩包

目录

应用场景

实现代码

扩展功能(生成压缩包)

小结 


应用场景

我们在一个求职简历打印的项目功能里,需要根据一定的查询条件,得到结果并批量导出指定格式的文件。导出的格式可能有多种,比如WORD格式、EXCEL格式、PDF格式等,实现方式是通过设置对应的模板进行输出,实际情况是,简历的内容是灵活设置的,没有固定的格式,模板数量是不固定的。

通过动态页面技术,可以实现简历配置后的网页内容输出,但制作对应的各种模板会遇到开发效率和服务跟进的问题。为了保障原样输出,折中而简单的方案就是将动态输出的页面转化为图片格式。

实现代码

创建一个 UrlToImage 类,创建实例的时候传递指定的 URL, 并调用 SaveToImageFile(string outputFilename)方法,该方法传递要输出的文件名参数即可即可。

调用示例代码如下:

string url = "https://" + Request.Url.Host + "/printResume.aspx";
UrlToImage uti = new UrlToImage(url);
bool irv = uti.SaveToImageFile(Request.PhysicalApplicationPath + "\\test.jpg");
if(bool==false){Response.Write("save failed.");Response.End();
}

类及实现代码如下:

    public class UrlToImage{private  Bitmap m_Bitmap;private string m_Url;private string m_FileName = string.Empty;int initheight = 0;public UrlToImage(string url){// Without filem_Url = url;}public UrlToImage(string url, string fileName){// With filem_Url = url;m_FileName = fileName;}public Bitmap Generate(){// Threadvar m_thread = new Thread(_Generate);m_thread.SetApartmentState(ApartmentState.STA);m_thread.Start();m_thread.Join();return m_Bitmap;}public bool SaveToImageFile(string filename){Bitmap bt=Generate();if (bt == null){return false;}bt.Save(filename);return File.Exists(filename);}private void _Generate(){var browser = new WebBrowser { ScrollBarsEnabled = false };browser.ScriptErrorsSuppressed = true;initheight = 0;browser.Navigate(m_Url);browser.DocumentCompleted += WebBrowser_DocumentCompleted;while (browser.ReadyState != WebBrowserReadyState.Complete){Application.DoEvents();}browser.Dispose();}private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e){// Capturevar browser = (WebBrowser)sender;browser.ClientSize = new Size(browser.Document.Body.ScrollRectangle.Width, browser.Document.Body.ScrollRectangle.Bottom);browser.ScrollBarsEnabled = false;m_Bitmap = new Bitmap(browser.Document.Body.ScrollRectangle.Width, browser.Document.Body.ScrollRectangle.Bottom);browser.BringToFront();browser.DrawToBitmap(m_Bitmap, browser.Bounds);// Save as file?if (m_FileName.Length > 0){// Savem_Bitmap.SaveJPG100(m_FileName);}if (initheight == browser.Document.Body.ScrollRectangle.Bottom){browser.DocumentCompleted -= new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);}initheight = browser.Document.Body.ScrollRectangle.Bottom;}}

生成压缩包

 对于批量生成的图片文件,我们可以生成压缩包为客户提供下载功能,压缩功能引用的是ICSharpCode.SharpZipLib.dll,创建 ZipCompress 类的实例,ZipDirectory(zippath, zipfile, password) 方法,需要提供的参数包括,压缩的目录、生成的压缩文件名,压缩包的打开密码。

示例代码如下:

    string zippath = Request.PhysicalApplicationPath + "\\des\\" ;if (!Directory.Exists(zippath)){Directory.CreateDirectory(zippath);}string zipfile = Request.PhysicalApplicationPath + "\\des\\test.zip";ZipCompress allgzip = new ZipCompress();System.IO.DirectoryInfo alldi = new System.IO.DirectoryInfo(zippath);string password = "123456";allgzip.ZipDirectory(zippath, zipfile, password);//以下是生成完压缩包后,清除目录及文件string[] allfs = Directory.GetFiles(zippath);for (int i = 0; i < allfs.Length; i++){File.Delete(allfs[i]);}Directory.Delete(zippath);  

类及实现代码如下:

 public class ZipCompress{public  byte[] Compress(byte[] inputBytes){using (MemoryStream outStream = new MemoryStream()){using (GZipStream zipStream = new GZipStream(outStream, CompressionMode.Compress, true)){zipStream.Write(inputBytes, 0, inputBytes.Length);zipStream.Close(); //很重要,必须关闭,否则无法正确解压return outStream.ToArray();}}}public  byte[] Decompress(byte[] inputBytes){using (MemoryStream inputStream = new MemoryStream(inputBytes)){using (MemoryStream outStream = new MemoryStream()){using (GZipStream zipStream = new GZipStream(inputStream, CompressionMode.Decompress)){zipStream.CopyTo(outStream);zipStream.Close();return outStream.ToArray();}}}}public  string Compress(string input){byte[] inputBytes = Encoding.Default.GetBytes(input);byte[] result = Compress(inputBytes);return Convert.ToBase64String(result);}public  string Decompress(string input){byte[] inputBytes = Convert.FromBase64String(input);byte[] depressBytes = Decompress(inputBytes);return Encoding.Default.GetString(depressBytes);}public  void Compress(DirectoryInfo dir){foreach (FileInfo fileToCompress in dir.GetFiles()){Compress(fileToCompress);}}public  void Decompress(DirectoryInfo dir){foreach (FileInfo fileToCompress in dir.GetFiles()){Decompress(fileToCompress);}}public  void Compress(FileInfo fileToCompress){using (FileStream originalFileStream = fileToCompress.OpenRead()){if ((File.GetAttributes(fileToCompress.FullName) & FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz"){using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz")){using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress)){originalFileStream.CopyTo(compressionStream);}}}}}public  void Decompress(FileInfo fileToDecompress,string desfilename=""){using (FileStream originalFileStream = fileToDecompress.OpenRead()){string currentFileName = fileToDecompress.FullName;string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);if (desfilename != ""){newFileName = desfilename;}using (FileStream decompressedFileStream = File.Create(newFileName)){using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress)){decompressionStream.CopyTo(decompressedFileStream);}}}}public  void ZipDirectory(string folderToZip, string zipedFileName,string password){ZipDirectory(folderToZip, zipedFileName,(password==""?string.Empty:password), true, string.Empty, string.Empty, true);}public  void ZipDirectory(string folderToZip, string zipedFileName, string password, bool isRecurse, string fileRegexFilter, string directoryRegexFilter, bool isCreateEmptyDirectories){FastZip fastZip = new FastZip();fastZip.CreateEmptyDirectories = isCreateEmptyDirectories;fastZip.Password = password;fastZip.CreateZip(zipedFileName, folderToZip, isRecurse, fileRegexFilter, directoryRegexFilter);}public void UnZipDirectory(string zipedFileName, string targetDirectory, string password,string fileFilter=null){FastZip fastZip = new FastZip();fastZip.Password = password;fastZip.ExtractZip(zipedFileName, targetDirectory,fileFilter);}public void UnZip(string zipFilePath, string unZipDir){if (zipFilePath == string.Empty){throw new Exception("压缩文件不能为空!");}if (!File.Exists(zipFilePath)){throw new FileNotFoundException("压缩文件不存在!");}//解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹  if (unZipDir == string.Empty)unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath));if (!unZipDir.EndsWith("/"))unZipDir += "/";if (!Directory.Exists(unZipDir))Directory.CreateDirectory(unZipDir);using (var s = new ZipInputStream(File.OpenRead(zipFilePath))){ZipEntry theEntry;while ((theEntry = s.GetNextEntry()) != null){string directoryName = Path.GetDirectoryName(theEntry.Name);string fileName = Path.GetFileName(theEntry.Name);if (!string.IsNullOrEmpty(directoryName)){Directory.CreateDirectory(unZipDir + directoryName);}if (directoryName != null && !directoryName.EndsWith("/")){}if (fileName != String.Empty){using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name)){int size;byte[] data = new byte[2048];while (true){size = s.Read(data, 0, data.Length);if (size > 0){streamWriter.Write(data, 0, size);}else{break;}}}}}}}}

小结 

对于生成的图片文件,我们还可以结合其它的API应用,来判断图片是否有被PS的情况,来提升和扩展应用程序的功能。另外,对于被访问的动态页面,建议使用访问控制,只有正常登录或提供访问令牌的用户才可以生成结果图片,以保证数据的安全性。

以上代码仅供参考,欢迎大家指正,再次感谢您的阅读!

 

相关文章:

C# 实现网页内容保存为图片并生成压缩包

目录 应用场景 实现代码 扩展功能(生成压缩包) 小结 应用场景 我们在一个求职简历打印的项目功能里&#xff0c;需要根据一定的查询条件&#xff0c;得到结果并批量导出指定格式的文件。导出的格式可能有多种&#xff0c;比如WORD格式、EXCEL格式、PDF格式等&#xff0c;…...

C#_事件简述

事件模型简述 C#中事件的运行模式为"发布订阅模型"&#xff0c;事件触发者称为"发布者"&#xff0c;事件处理者称为"订阅者" 事件模型的五个组成部分 事件&#xff08;成员&#xff09;事件的拥有者&#xff08;类/对象&#xff09;事件的响应…...

C语言:指针(一)

目录 1.内存和地址2. 指针变量和地址2.1 取地址操作符&#xff08;&&#xff09;2.2 指针变量和解引用操作符&#xff08;*&#xff09;2.2.1 指针变量2.2.2 解引用操作符&#xff08;*&#xff09; 2.3 指针变量的大小 3.指针变量的类型和意义3.1 指针的解引用3.2 指针 -指…...

【leetcode刷题之路】面试经典150题(3)——哈希表+区间

文章目录 5 哈希表5.1 【哈希表】赎金信5.2 【数学】同构字符串5.3 【数学】单词规律5.4 【哈希表】有效的字母异位词5.5 【哈希表】字母异位词分组5.6 【双指针】两数之和5.7 【数学】快乐数5.8 【哈希表】219. 存在重复元素 II5.9 【数学】最长连续序列 6 区间6.1 【数学】汇…...

群晖NAS DSM7.2.1安装宝塔之后无法登陆账号密码问题解决

宝塔的安装就不在这赘述了&#xff0c;只说下&#xff0c;启动之后默认账号密码无法登陆的问题。 按照上面给出的账号密码&#xff0c;无法登陆 然后点忘记密码&#xff0c;由于是docker安装的&#xff0c;根目录下没有/www/server/panel 。 也没有bt命令 要怎么修改呢。 既然…...

9、使用 ChatGPT 的 GPT 制作自己的 GPT!

使用 ChatGPT 的 GPT 制作自己的 GPT! 想用自己的 GPT 超越 GPT ChatGPT 吗?那么让我们 GPT GPT 吧! 山姆 奥特曼利用这个机会在推特上宣传 GPTs 的同时还猛烈抨击了埃隆的格罗克。 GPTs概览 他们来了! 在上周刚刚宣布之后,OpenAI 现在推出了其雄心勃勃的新 ChatGPT…...

企业微信应用开发:使用Cpolar域名配置进行本地接口回调的调试指南

文章目录 1. Windows安装Cpolar2. 创建Cpolar域名3. 创建企业微信应用4. 定义回调本地接口5. 回调和可信域名接口校验6. 设置固定Cpolar域名7. 使用固定域名校验 企业微信开发者在应用的开发测试阶段&#xff0c;应用服务通常是部署在开发环境&#xff0c;在有数据回调的开发场…...

js 可选链运算符(?.)空值合并运算符(??)逻辑空赋值运算符(??=)

可选链运算符&#xff08;?.&#xff09;允许读取位于连接对象链深处的属性的值&#xff0c;而不必明确验证链中的每个引用是否有效。?. 运算符的功能类似于 . 链式运算符&#xff0c;不同之处在于&#xff0c;在引用为空 (nullish ) (null 或者 undefined) 的情况下不会引起…...

vue 手势解锁功能

效果 实现 <script setup lang"ts"> const canvasRef ref<HTMLCanvasElement>() const ctx ref<CanvasRenderingContext2D | null>(null) const width px2px(600) const height px2px(700) const radius ref(px2px(50))const init () > …...

介绍 CI / CD

目录 一、介绍 CI / CD 1、为什么要 CI / CD 方法简介 1、持续集成 2、持续交付 3、持续部署 2、GitLab CI / CD简介 3、GitLab CI / CD 的工作原理 4、基本CI / CD工作流程 5、首次设置 GitLab CI / CD 6、GitLab CI / CD功能集 一、介绍 CI / CD 在本文档中&#x…...

Stable Diffusion 3 Early Preview发布

2月22日&#xff0c;Stability AI 发布了 Stable Diffusion 3 early preview&#xff0c;这是一种开放权重的下一代图像合成模型。据报道&#xff0c;它继承了其前身&#xff0c;生成了详细的多主题图像&#xff0c;并提高了文本生成的质量和准确性。这一简短的公告并未附带公开…...

【解决(几乎)任何机器学习问题】:特征选择

当你创建了成千上万个特征后&#xff0c;就该从中挑选出⼏个了。但是&#xff0c;我们绝不应该创建成百上千个⽆⽤的特征。特征过多会带来⼀个众所周知的问题&#xff0c;即 "维度诅咒"。如果你有很多特征&#xff0c;你也必须有很多训练样本来捕捉所有特征。什么是 …...

24 双非计算机秋招总结

引言 我整理了一份 10w 字数的前端技术文档&#xff08;飞书&#xff09;&#xff0c;地址&#xff1a;https://qx8wba2yxsl.feishu.cn/docx/Vb5Zdq7CGoPAsZxMLztc53E1n0k?fromfrom_copylink&#xff0c;欢迎对前端感兴趣的同学查看、共建、分享。 PS&#xff1a;我是一名大四…...

用友NC65与用友NCC对接集成NC65-凭证列表查询打通凭证新增

用友NC65与用友NCC对接集成NC65-凭证列表查询打通凭证新增 数据源平台:用友NC65 用友NC是为集团与行业企业提供的全线管理软件产品&#xff0c;由亚太本土最大的企业管理软件提供商用友公司研发提供&#xff0c;用友NC率先采用J2EE架构和先进开放的集团级开发平台UAP&#xff0…...

【初中生讲机器学习】12. 似然函数和极大似然估计:原理、应用与代码实现

创建时间&#xff1a;2024-02-23 最后编辑时间&#xff1a;2024-02-24 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名初三学生&#xff0c;热爱计算机和数学&#xff0c;我们一起加…...

【达梦数据库】查看pesg回滚段信息的视图和SQL

一些达梦回滚段是使用情况的查询SQL&#xff0c;供排查“回滚记录版本太旧&#xff0c;无法获取用户记录” 等类似问题时使用 视图名说明主库备库v$pseg_items显示回滚系统中当前回滚项信息&#xff08;回滚线程的工作信息&#xff09;总行数WORKER_THREADS1查询 no rowsv$pseg…...

UML---活动图

活动图概述 活动图&#xff08;Activity Diagram&#xff09;是UML&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;中的一种行为建模工具&#xff0c;主要用于描述系统或业务流程中的一系列活动或操作。活动图通常用于描述用例中的行为&#xff0c…...

编程笔记 Golang基础 018 常量与变量

编程笔记 Golang基础 018 常量与变量 一、常量常量的定义iota特性 二、变量变量定义变量作用域零值与初始化类型转换注意事项 三、重要性 常量&#xff0c;就是在程序编译阶段就确定下来的值&#xff0c;而程序在运行时则无法改变该值。变量是程序的基本组成单位&#xff0c;用…...

如何使用Douglas-042为威胁搜索和事件应急响应提速

关于Douglas-042 Douglas-042是一款功能强大的PowerShell脚本&#xff0c;该脚本可以提升数据分类的速度&#xff0c;并辅助广大研究人员迅速从取证数据中筛选和提取出关键数据。 该工具能够搜索和识别Windows生态系统中潜在的安全漏洞&#xff0c;Douglas-042会将注意力放在…...

华为配置WLAN AC和AP之间VPN穿越示例

配置WLAN AC和AP之间VPN穿越示例 组网图形 图1 配置WLAN AC和AP之间VPN穿越示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户接入WLAN网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...