项目背景

公司某项目上有一需求:要对合同、验收、付款申请单等审批页面进行截图,并生成Pdf文件回传到影像系统做最终的归档。然后衍生出来了一个WinForm的自动截图工具,其大致的实现逻辑是:定时请求数据库,抓取带截图的数据,组装得到审批页面地址,winfrom中引用WebView进行加载地址,在OnLoadingFinish加载完成方法里面,通过ScreenShot()获取等到Bitmap对象,然后在进行pdf文档的生成。

弊端:因为是前后端分离的项目,OnLoadingFinish中无法判定ajax请求是否完毕,还需要定时器进行延迟截图、保存;其次是稳定性不高,可能是技术问题,经常导致程序奔溃,并且winform无法捕获到异常,但是另外一个项目崩溃几率很小,可能是数据量小吧

重构

基于原项目使用的WebVIew,控件老旧,并且功能不太优化,所以采用了PuppeteerSharp进行了重构。

运行环境:Windows 服务器
开发环境:Vs@2017、.net framework 4.6以及以上,本项目4.8

PuppeteerSharp

Puppeteer是一个通过 DevTools Protocol 控制 headless chrome 的 high-level Node 库,也可以通过设置使用 非 headless Chrome。

我们手工可以在浏览器上做的事情,Puppeteer 都能胜任:

  1. 生成网页截图或者 PDF
  2. 爬取大量异步渲染内容的网页,基本就是人肉爬虫
  3. 模拟键盘输入、表单自动提交、UI 自动化测试

PuppeteerSharp是官方Node.JS Puppeteer API的.NET移植。

1.由于Puppeteer-Sharp是NetStandard 2.0库,因此最低平台版本是.NET Framework 4.6.1和.NET Core 2.0

2.支持WebSocket库的最低Windows版本是Windows 8和Windows Server 2012,具体参见 System.Net.WebSockets Namespace | Microsoft Docs

安装

1.使用Nuget搜索PuppeteerSharp,找到PuppeteerSharp点击安装即可。

PuppeteerSharp的使用

1.获取Browsers对象

private async Task<Browser> Browsers(){try{await slimLock.WaitAsync();// 已经拷贝了.local-chromium,不需要再下载了//await new BrowserFetcher().DownloadAsync();if (_browser == null){_browser = await Puppeteer.LaunchAsync(new LaunchOptions{Headless = true, DefaultViewport = null,//Args = new string[] {//    "--disable-infobars",//隐藏 自动化标题//    "--no-sandbox", // 沙盒模式//    "--start-maximized" // 最大化//}}); ;return _browser;}return _browser;}catch (Exception ex){throw ex;}finally{slimLock.Release();}}

2.生成Pdf,注意看注释,方法中有俩种逻辑【一种是先生成图片,然后图片转成pdf;一种是官方的生成pdf的方法,只不过官方的会有分页,长页面看着不太优化,所以采用了第一种方式】

private async Task BrowsersPageToPdf(string loadUrl, string savePath){var page = await _browser.NewPageAsync();// 设置页面分辨率await page.SetViewportAsync( new ViewPortOptions(){ Width = 1400, Height = 1050 });ScreenshotLoading("页面加载完成,等待数据渲染");//load: window.onload事件被触发时候完成导航,某些情况下它根本不会发生。//domcontentloaded: Domcontentloaded事件触发时候认为导航成功//networkidle0: 在 500ms 内没有网络连接时就算成功(全部的request结束),才认为导航结束//networkidle2: 500ms 内有不超过 2 个网络连接时就算成功(还有两个以下的request),就认为导航完成//加载时长 networkidle0 > networkidle2 > load > domcontentloadedawait page.GoToAsync(loadUrl, new NavigationOptions() { WaitUntil = new WaitUntilNavigation[] { WaitUntilNavigation.Networkidle0 } });ScreenshotLoading("页面加载完成,数据渲染完成,页面截图中....");ScreenshotOptions screenshotOptions = new ScreenshotOptions();//screenshotOptions.Clip = new PuppeteerSharp.Media.Clip() { Height = 0, Width = 0, X = 0, Y = 0 };//设置截剪区域screenshotOptions.FullPage = true; //是否截取整个页面screenshotOptions.OmitBackground = false;//是否使用透明背景,而不是默认白色背景screenshotOptions.Quality = 100; //截图质量 0-100(png不可用)screenshotOptions.Type = ScreenshotType.Jpeg; //截图格式var saveFile = System.IO.Path.GetDirectoryName(savePath);if (!Directory.Exists(saveFile)){FileInfo fi = new FileInfo(saveFile);Directory.CreateDirectory(fi.DirectoryName);}string imgUrl = saveFile + "\\" +  CurrentHandlerData.DataKey + "_" + Guid.NewGuid() + ".jpg";await page.ScreenshotAsync(imgUrl, screenshotOptions);ScreenshotLoading("页面截图完成,正在转Pdf文件...");//var stream = await page.ScreenshotStreamAsync();CommonHelper.ConvertJpg2Pdf(imgUrl, savePath);ScreenshotLoading("页面截图完成,Pdf文件生成成功!");CommonHelper.FileDel(imgUrl);ScreenshotLoading("页面截图文件删除成功!");//官方生成Pdf方法//设置PDF选项//PdfOptions pdfOptions = new PdfOptions();//pdfOptions.DisplayHeaderFooter = false; //是否显示页眉页脚//pdfOptions.FooterTemplate = "";   //页脚文本//pdfOptions.Format = new PuppeteerSharp.Media.PaperFormat(11.27m, 30m);  //pdf纸张格式 英寸为单位 pdfOptions.Format = PaperFormat.A4;//pdfOptions.PrintBackground = true; // false pdf文件为灰白色,一些背景色也显示出来; true 页面为彩色//pdfOptions.HeaderTemplate = "";   //页眉文本//pdfOptions.Landscape = false;     //纸张方向 false-垂直 true-水平//pdfOptions.MarginOptions = new PuppeteerSharp.Media.MarginOptions() { Bottom = "0px", Left = "0px", Right = "0px", Top = "0px" }; //纸张边距,需要设置带单位的值,默认值是None//pdfOptions.Scale = 1m;            //PDF缩放,从0-1//await page.PdfAsync(savePath, pdfOptions);await page.DisposeAsync();}

坑点:

1.puppeteer需要Chromium 内核用以加载网页,所以要先调用类库的下载sdk,他自动帮你下载Chromium ,这也可能导致第一次没有Chromium会卡一阵子,因为在下载 ,完成之后,再程序根目录【bin/Debug】下会发现.local-chromium 的一个文件夹

2.获取Browser对象时,如果LaunchOptions.Headless设置为false,不能进行pdf文件生成,可以截图,同时可以看到程序调用的headless chrome的窗口

3.LaunchOptions.DefaultViewport 为null,浏览的页面会默认浏览器窗口大小,也可以自定义其大小【没有试过】,否则的话,在chrome中可以看到,右边会有部分留白

4.截图之前最好设置下分辨率:SetViewportAsync,否则图可能截不全

5.有的复杂网页可能要加载一段时间,不然截图是空白或者不完整的,可以延时或者使用类库提供的等待方法【特别是前后端分离的项目,注意看生成pdf方法中的注释】

其他

PuppeteerSharp还可以进行:向网页中注入HTML、执行Javascript(js)代码、连接到远程浏览器等等其他功能,也可以用于爬虫场景,其他功能可以看下官方介绍

图片转Pdf方法:

public static void ConvertJpg2Pdf(string jpgfile, string pdf){var document = new Document();using (var stream = new FileStream(pdf, FileMode.Create, FileAccess.Write, FileShare.None)){var pdfWriter = PdfWriter.GetInstance(document, stream);using (var imageStream = new FileStream(jpgfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){var image = iTextSharp.text.Image.GetInstance(imageStream);pdfWriter.CloseStream = false;document.SetPageSize(new iTextSharp.text.Rectangle(image.Width + 72f, image.Height + 72f));//(WWidth + 72f, HHeight + 72f));document.Open();image.Alignment = iTextSharp.text.Image.ALIGN_MIDDLE;document.Add(image);}document.Close();}}

C# Winform 使用 PuppeteerSharp 进行网页截图、生成pdf等操作相关推荐

  1. 如何在网页中生成PDF

    一.背景 开发工作中,需要实现网页生成 PDF 的功能,生成的 PDF 需上传至服务端,将 PDF 地址作为参数请求外部接口,这个转换过程及转换后的 PDF 不需要在前端展示给用户. 二.技术选型 该 ...

  2. 将不可复制、不可打印的电子书批量截图生成PDF

    首先感谢作者mainIdear的博文<当当·亚马逊·京东等加密的电子书转为PDF>为我搞定加密电子书转PDF提供帮助. 我准备搞的电子书就是下图这个,文字不能复制,也无法打印,无下一页按钮 ...

  3. 在线转换pdf和虚拟打印机生成pdf文件操作攻略

    由于PDF具有稳定的格式和良好的视图,使得PDF格式文件越来越受工作族的欢迎.但大多人仍习惯Word编辑,所以就有了Word文档转换PDF的需求,那么有什么好的转换Word的方法呢? 小编就来介绍两种 ...

  4. iTextSharp简单生成pdf和操作pdf添加水印

    遇到需要导出页面到pdf,并添加pdf水印的业务.稍微研究了下,借阅网友的前车之鉴,经过使用可行之后的代码贴出来,做个记录,也供需要的网友借阅. public classPDFSetWaterMark ...

  5. 有了 serverless,前端也可以快速开发一个 Puppeteer 网页截图服务

    更多云原生技术资讯可关注阿里巴巴云原生技术圈. Puppeteer 是什么? puppeteer 官网的介绍如下: Puppeteer is a Node library which provides ...

  6. Serverless 实战 —— 前端也可以快速开发一个 Puppeteer 网页截图服务

    Serverless 实战 -- 前端也可以快速开发一个 Puppeteer 网页截图服务 更多云原生技术资讯可关注阿里巴巴云原生技术圈. Puppeteer 是什么? puppeteer 官网的介绍 ...

  7. 生成的url无法显示_快速生成PDF文档~~

    官方文档:https://pypi.org/project/pdfkit/ 1.安装并配置环境 1)安装python-pdfkit:$ pip install pdfkit2)安装wkhtmltopd ...

  8. Java纯后端生成PDF格式报表的三种方案(包含echarts图表)

    最近做了一个奇葩的需求,研究了一下Java纯后端生成PDF报表的方案,顺便将研究的方案做个总结复盘,分享一下. 需求分析:Java后端定时任务统计汇总成报表数据,并生成PDF格式的报表文件,并通过邮件 ...

  9. pdfkit生成pdf,可用于notebook

    1.安装pdfkit库 在命令行中输入如下命令 pip install pdfkit 出现上面的Successfully installed pdfkit-0.6.1提示,说明安装成功了 2.安装wk ...

  10. 将网页保存为PDF的几种方法

    方法一  虚拟打印机打印(1) 优点:字体正常.公式正常.文字可选 不足:链接失效优点:字体正常.公式正常.文字可选 工具:IE 浏览器 Foxit Reader PDF Printer 步骤: 1. ...

最新文章

  1. Exchange2007中创建和访问公用文件夹
  2. android之音乐播放和音效播放
  3. 3.1.1 存储器的分类(半导体-磁芯-磁表面-光存储-ROM-RAM-永久非永久-内存-外存-Cache)
  4. 对于XLS碎片提取的深入研究
  5. machine id linux,linux – 机器ID是uuid吗?
  6. 空格分隔输出(信息学奥赛一本通-T1026)
  7. openssl req
  8. DPABI advanced edition 文件夹组织形式
  9. python购物车代码_python简单商城购物车实例代码
  10. 常用邮箱SMTP、POP3域名及其端口号
  11. iOS11降级到iOS10.3.3/10.3.2教程
  12. 系统分析与设计之用例图
  13. python批量下载邮件附件
  14. 湖大计算机人工智能专业导师,湖南大学考研研究生导师简介-贺旭
  15. java mysql点赞功能_用Java做一个类似于微博QQ空间点赞的功能-Fun言
  16. Ycbcr通道概念、SRCNN基本算法及基本细节
  17. 放假前的最后一次带薪摸鱼
  18. μTorrent 3.2.1 关闭广告
  19. 学习型索引在数据库中的应用实践
  20. Socket/Tcp游戏通信(一)-IP和端口号

热门文章

  1. Redis由于目标计算机积极拒绝,无法连接。
  2. 服务启动类型:自动、自动(延时启动)、手动、禁用
  3. [转]performSelector延时调用导致的内存泄露
  4. “2019年全国职业院校技能大赛”高职组计算机网络应用竞赛竞赛样题C卷(软件定义网络部分答案参考)
  5. 微信小程序豆瓣电影(上)
  6. 针式打印机windows打印乱码(并口模式与DOS打印测试)
  7. 2021年秋互联网思维期末考试
  8. 数模电路基础知识 —— 2. 常见电路符号说明 (导线、电源、接地、变压器与保险丝)
  9. Egret Engine(二十六):MovieClip序列帧动画
  10. 逆向分析学习入门教程