C# Winform 使用 PuppeteerSharp 进行网页截图、生成pdf等操作
項(xiàng)目背景
? ? ? ? 公司某項(xiàng)目上有一需求:要對(duì)合同、驗(yàn)收、付款申請(qǐng)單等審批頁(yè)面進(jìn)行截圖,并生成Pdf文件回傳到影像系統(tǒng)做最終的歸檔。然后衍生出來(lái)了一個(gè)WinForm的自動(dòng)截圖工具,其大致的實(shí)現(xiàn)邏輯是:定時(shí)請(qǐng)求數(shù)據(jù)庫(kù),抓取帶截圖的數(shù)據(jù),組裝得到審批頁(yè)面地址,winfrom中引用WebView進(jìn)行加載地址,在OnLoadingFinish加載完成方法里面,通過(guò)ScreenShot()獲取等到Bitmap對(duì)象,然后在進(jìn)行pdf文檔的生成。
? ? ? ? 弊端:因?yàn)槭乔昂蠖朔蛛x的項(xiàng)目,OnLoadingFinish中無(wú)法判定ajax請(qǐng)求是否完畢,還需要定時(shí)器進(jìn)行延遲截圖、保存;其次是穩(wěn)定性不高,可能是技術(shù)問(wèn)題,經(jīng)常導(dǎo)致程序奔潰,并且winform無(wú)法捕獲到異常,但是另外一個(gè)項(xiàng)目崩潰幾率很小,可能是數(shù)據(jù)量小吧
重構(gòu)
? ? ? ? 基于原項(xiàng)目使用的WebVIew,控件老舊,并且功能不太優(yōu)化,所以采用了PuppeteerSharp進(jìn)行了重構(gòu)。
運(yùn)行環(huán)境:Windows 服務(wù)器 開(kāi)發(fā)環(huán)境:Vs@2017、.net framework 4.6以及以上,本項(xiàng)目4.8PuppeteerSharp?
????????Puppeteer是一個(gè)通過(guò) DevTools Protocol 控制 headless chrome 的 high-level Node 庫(kù),也可以通過(guò)設(shè)置使用 非 headless Chrome。
我們手工可以在瀏覽器上做的事情,Puppeteer 都能勝任:
????????PuppeteerSharp是官方Node.JS Puppeteer API的.NET移植。
? ? ? ? 1.由于Puppeteer-Sharp是NetStandard 2.0庫(kù),因此最低平臺(tái)版本是.NET Framework 4.6.1和.NET Core 2.0
? ? ? ? 2.支持WebSocket庫(kù)的最低Windows版本是Windows 8和Windows Server 2012,具體參見(jiàn)?System.Net.WebSockets Namespace | Microsoft Docs
安裝
? ? ? ? 1.使用Nuget搜索PuppeteerSharp,找到PuppeteerSharp點(diǎn)擊安裝即可。
PuppeteerSharp的使用? ? ?
? ? ? ? ?1.獲取Browsers對(duì)象
private async Task<Browser> Browsers(){try{await slimLock.WaitAsync();// 已經(jīng)拷貝了.local-chromium,不需要再下載了//await new BrowserFetcher().DownloadAsync();if (_browser == null){_browser = await Puppeteer.LaunchAsync(new LaunchOptions{Headless = true, DefaultViewport = null,//Args = new string[] {// "--disable-infobars",//隱藏 自動(dòng)化標(biāo)題// "--no-sandbox", // 沙盒模式// "--start-maximized" // 最大化//}}); ;return _browser;}return _browser;}catch (Exception ex){throw ex;}finally{slimLock.Release();}}? ? ? ? 2.生成Pdf,注意看注釋,方法中有倆種邏輯【一種是先生成圖片,然后圖片轉(zhuǎn)成pdf;一種是官方的生成pdf的方法,只不過(guò)官方的會(huì)有分頁(yè),長(zhǎng)頁(yè)面看著不太優(yōu)化,所以采用了第一種方式】
private async Task BrowsersPageToPdf(string loadUrl, string savePath){var page = await _browser.NewPageAsync();// 設(shè)置頁(yè)面分辨率await page.SetViewportAsync( new ViewPortOptions(){ Width = 1400, Height = 1050 });ScreenshotLoading("頁(yè)面加載完成,等待數(shù)據(jù)渲染");//load: window.onload事件被觸發(fā)時(shí)候完成導(dǎo)航,某些情況下它根本不會(huì)發(fā)生。//domcontentloaded: Domcontentloaded事件觸發(fā)時(shí)候認(rèn)為導(dǎo)航成功//networkidle0: 在 500ms 內(nèi)沒(méi)有網(wǎng)絡(luò)連接時(shí)就算成功(全部的request結(jié)束),才認(rèn)為導(dǎo)航結(jié)束//networkidle2: 500ms 內(nèi)有不超過(guò) 2 個(gè)網(wǎng)絡(luò)連接時(shí)就算成功(還有兩個(gè)以下的request),就認(rèn)為導(dǎo)航完成//加載時(shí)長(zhǎng) networkidle0 > networkidle2 > load > domcontentloadedawait page.GoToAsync(loadUrl, new NavigationOptions() { WaitUntil = new WaitUntilNavigation[] { WaitUntilNavigation.Networkidle0 } });ScreenshotLoading("頁(yè)面加載完成,數(shù)據(jù)渲染完成,頁(yè)面截圖中....");ScreenshotOptions screenshotOptions = new ScreenshotOptions();//screenshotOptions.Clip = new PuppeteerSharp.Media.Clip() { Height = 0, Width = 0, X = 0, Y = 0 };//設(shè)置截剪區(qū)域screenshotOptions.FullPage = true; //是否截取整個(gè)頁(yè)面screenshotOptions.OmitBackground = false;//是否使用透明背景,而不是默認(rèn)白色背景screenshotOptions.Quality = 100; //截圖質(zhì)量 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("頁(yè)面截圖完成,正在轉(zhuǎn)Pdf文件...");//var stream = await page.ScreenshotStreamAsync();CommonHelper.ConvertJpg2Pdf(imgUrl, savePath);ScreenshotLoading("頁(yè)面截圖完成,Pdf文件生成成功!");CommonHelper.FileDel(imgUrl);ScreenshotLoading("頁(yè)面截圖文件刪除成功!");//官方生成Pdf方法//設(shè)置PDF選項(xiàng)//PdfOptions pdfOptions = new PdfOptions();//pdfOptions.DisplayHeaderFooter = false; //是否顯示頁(yè)眉頁(yè)腳//pdfOptions.FooterTemplate = ""; //頁(yè)腳文本//pdfOptions.Format = new PuppeteerSharp.Media.PaperFormat(11.27m, 30m); //pdf紙張格式 英寸為單位 pdfOptions.Format = PaperFormat.A4;//pdfOptions.PrintBackground = true; // false pdf文件為灰白色,一些背景色也顯示出來(lái); true 頁(yè)面為彩色//pdfOptions.HeaderTemplate = ""; //頁(yè)眉文本//pdfOptions.Landscape = false; //紙張方向 false-垂直 true-水平//pdfOptions.MarginOptions = new PuppeteerSharp.Media.MarginOptions() { Bottom = "0px", Left = "0px", Right = "0px", Top = "0px" }; //紙張邊距,需要設(shè)置帶單位的值,默認(rèn)值是None//pdfOptions.Scale = 1m; //PDF縮放,從0-1//await page.PdfAsync(savePath, pdfOptions);await page.DisposeAsync();}坑點(diǎn):
? ? ? ? 1.puppeteer需要Chromium 內(nèi)核用以加載網(wǎng)頁(yè),所以要先調(diào)用類(lèi)庫(kù)的下載sdk,他自動(dòng)幫你下載Chromium ,這也可能導(dǎo)致第一次沒(méi)有Chromium會(huì)卡一陣子,因?yàn)樵谙螺d ,完成之后,再程序根目錄【bin/Debug】下會(huì)發(fā)現(xiàn).local-chromium 的一個(gè)文件夾
? ? ? ? 2.獲取Browser對(duì)象時(shí),如果LaunchOptions.Headless設(shè)置為false,不能進(jìn)行pdf文件生成,可以截圖,同時(shí)可以看到程序調(diào)用的headless chrome的窗口
? ? ? ? 3.LaunchOptions.DefaultViewport 為null,瀏覽的頁(yè)面會(huì)默認(rèn)瀏覽器窗口大小,也可以自定義其大小【沒(méi)有試過(guò)】,否則的話(huà),在chrome中可以看到,右邊會(huì)有部分留白
? ? ? ? 4.截圖之前最好設(shè)置下分辨率:SetViewportAsync,否則圖可能截不全
? ? ? ? 5.有的復(fù)雜網(wǎng)頁(yè)可能要加載一段時(shí)間,不然截圖是空白或者不完整的,可以延時(shí)或者使用類(lèi)庫(kù)提供的等待方法【特別是前后端分離的項(xiàng)目,注意看生成pdf方法中的注釋】
其他
????????PuppeteerSharp還可以進(jìn)行:向網(wǎng)頁(yè)中注入HTML、執(zhí)行Javascript(js)代碼、連接到遠(yuǎn)程瀏覽器等等其他功能,也可以用于爬蟲(chóng)場(chǎng)景,其他功能可以看下官方介紹
? ? ? ? 圖片轉(zhuǎn)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();}}總結(jié)
以上是生活随笔為你收集整理的C# Winform 使用 PuppeteerSharp 进行网页截图、生成pdf等操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java做抽奖系统怎么搞_JAVA 随机
- 下一篇: C# 读写视频文件