背景
最近再做一个需求,需要对网页生成预览图,如下图
但是网页千千万,总不能一个个打开,截图吧;于是想着能不能使用代码来实现网页的截图。其实要实现这个功能,无非就是要么实现一个仿真浏览器,要么调用系统浏览器,再进行截图操作。
代码实现
1、启用线程Thread
void startPrintScreen(ScreenShotParam requestParam){Thread thread = new Thread(new ParameterizedThreadStart(do_PrintScreen));thread.SetApartmentState(ApartmentState.STA);thread.Start(requestParam);if (requestParam.Wait){thread.Join();FileInfo result = new FileInfo(requestParam.SavePath);long minSize = 1 * 1024;// 太小可能是空白圖,重抓int maxRepeat = 2; while ((!result.Exists || result.Length <= minSize) && maxRepeat > 0){thread = new Thread(new ParameterizedThreadStart(do_PrintScreen));thread.SetApartmentState(ApartmentState.STA);thread.Start(requestParam);thread.Join();maxRepeat--;}}}
2、模拟浏览器WebBrowser
void do_PrintScreen(object param){try{ScreenShotParam screenShotParam = (ScreenShotParam)param;string requestUrl = screenShotParam.Url;string savePath = screenShotParam.SavePath;WebBrowser wb = new WebBrowser();wb.ScrollBarsEnabled = false;wb.ScriptErrorsSuppressed = true;wb.Navigate(requestUrl);logger.Debug("wb.Navigate");DateTime startTime = DateTime.Now;TimeSpan waitTime = new TimeSpan(0, 0, 0, 10, 0);// 10 secondwhile (wb.ReadyState != WebBrowserReadyState.Complete){Application.DoEvents();if (DateTime.Now - startTime > waitTime){wb.Dispose();logger.Debug("wb.Dispose() timeout");return;}}wb.Width = screenShotParam.Left + screenShotParam.Width + screenShotParam.Left; // wb.Document.Body.ScrollRectangle.Width (避掉左右側的邊線);wb.Height = screenShotParam.Top + screenShotParam.Height; // wb.Document.Body.ScrollRectangle.Height;wb.ScrollBarsEnabled = false;wb.Document.Body.Style = "overflow:hidden";//hide scroll barvar doc = (wb.Document.DomDocument) as mshtml.IHTMLDocument2;var style = doc.createStyleSheet("", 0);style.cssText = @"img { border-style: none; }";Bitmap bitmap = new Bitmap(wb.Width, wb.Height);wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height));wb.Dispose();logger.Debug("wb.Dispose()");bitmap = CutImage(bitmap, new Rectangle(screenShotParam.Left, screenShotParam.Top, screenShotParam.Width, screenShotParam.Height));bool needResize = screenShotParam.Width > screenShotParam.ResizeMaxWidth || screenShotParam.Height > screenShotParam.ResizeMaxWidth;if (needResize){double greaterLength = bitmap.Width > bitmap.Height ? bitmap.Width : bitmap.Height;double ratio = screenShotParam.ResizeMaxWidth / greaterLength;bitmap = Resize(bitmap, ratio);}bitmap.Save(savePath, System.Drawing.Imaging.ImageFormat.Gif);bitmap.Dispose();logger.Debug("bitmap.Dispose();");logger.Debug("finish");}catch (Exception ex){logger.Info($"exception: {ex.Message}");}}
3、截图操作
private static Bitmap CutImage(Bitmap source, Rectangle p){// An empty bitmap which will hold the cropped imageBitmap bmp = new Bitmap(p.Width, p.Height);//using (Bitmap bmp = new Bitmap(p.Width, p.Height)){Graphics g = Graphics.FromImage(bmp);// Draw the given area (p) of the source image// at location 0,0 on the empty bitmap (bmp)g.DrawImage(source, 0, 0, p, GraphicsUnit.Pixel);return bmp;}}private static Bitmap Resize(Bitmap originImage, Double times){int width = Convert.ToInt32(originImage.Width * times);int height = Convert.ToInt32(originImage.Height * times);return ResizeProcess(originImage, originImage.Width, originImage.Height, width, height);}
完整代码
public static string ScreenShotAndSaveAmazonS3(string account, string locale, Guid rule_ID, Guid template_ID){//新的Templatevar url = string.Format("https://xxxx/public/previewtemplate?showTemplateName=0&locale={0}&inputTemplateId={1}&inputThemeId=&Account={2}",locale,template_ID,account);var tempPath = Tools.GetAppSetting("TempPath");//路徑準備var userPath = AmazonS3.GetS3UploadDirectory(account, locale, AmazonS3.S3SubFolder.Template);var fileName = string.Format("{0}.gif", template_ID);var fullFilePath = Path.Combine(userPath.LocalDirectoryPath, fileName);logger.Debug("userPath: {0}, fileName: {1}, fullFilePath: {2}, url:{3}", userPath, fileName, fullFilePath, url);//開始截圖,並暫存在本機var screen = new Screen();screen.ScreenShot(url, fullFilePath);//將截圖,儲存到 Amazon S3//var previewImageUrl = AmazonS3.UploadFile(fullFilePath, userPath.RemotePath + fileName);return string.Empty;}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;namespace PrintScreen.Common
{public class Screen{protected static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();public void ScreenShot(string url, string path, int width = 400, int height = 300, int left = 50, int top = 50, int resizeMaxWidth = 200, int wait = 1){if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(path)){ScreenShotParam requestParam = new ScreenShotParam{Url = url,SavePath = path,Width = width,Height = height,Left = left,Top = top,ResizeMaxWidth = resizeMaxWidth,Wait = wait != 0};startPrintScreen(requestParam);}}void startPrintScreen(ScreenShotParam requestParam){Thread thread = new Thread(new ParameterizedThreadStart(do_PrintScreen));thread.SetApartmentState(ApartmentState.STA);thread.Start(requestParam);if (requestParam.Wait){thread.Join();FileInfo result = new FileInfo(requestParam.SavePath);long minSize = 1 * 1024;// 太小可能是空白圖,重抓int maxRepeat = 2; while ((!result.Exists || result.Length <= minSize) && maxRepeat > 0){thread = new Thread(new ParameterizedThreadStart(do_PrintScreen));thread.SetApartmentState(ApartmentState.STA);thread.Start(requestParam);thread.Join();maxRepeat--;}}}void do_PrintScreen(object param){try{ScreenShotParam screenShotParam = (ScreenShotParam)param;string requestUrl = screenShotParam.Url;string savePath = screenShotParam.SavePath;WebBrowser wb = new WebBrowser();wb.ScrollBarsEnabled = false;wb.ScriptErrorsSuppressed = true;wb.Navigate(requestUrl);logger.Debug("wb.Navigate");DateTime startTime = DateTime.Now;TimeSpan waitTime = new TimeSpan(0, 0, 0, 10, 0);// 10 secondwhile (wb.ReadyState != WebBrowserReadyState.Complete){Application.DoEvents();if (DateTime.Now - startTime > waitTime){wb.Dispose();logger.Debug("wb.Dispose() timeout");return;}}wb.Width = screenShotParam.Left + screenShotParam.Width + screenShotParam.Left; // wb.Document.Body.ScrollRectangle.Width (避掉左右側的邊線);wb.Height = screenShotParam.Top + screenShotParam.Height; // wb.Document.Body.ScrollRectangle.Height;wb.ScrollBarsEnabled = false;wb.Document.Body.Style = "overflow:hidden";//hide scroll barvar doc = (wb.Document.DomDocument) as mshtml.IHTMLDocument2;var style = doc.createStyleSheet("", 0);style.cssText = @"img { border-style: none; }";Bitmap bitmap = new Bitmap(wb.Width, wb.Height);wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height));wb.Dispose();logger.Debug("wb.Dispose()");bitmap = CutImage(bitmap, new Rectangle(screenShotParam.Left, screenShotParam.Top, screenShotParam.Width, screenShotParam.Height));bool needResize = screenShotParam.Width > screenShotParam.ResizeMaxWidth || screenShotParam.Height > screenShotParam.ResizeMaxWidth;if (needResize){double greaterLength = bitmap.Width > bitmap.Height ? bitmap.Width : bitmap.Height;double ratio = screenShotParam.ResizeMaxWidth / greaterLength;bitmap = Resize(bitmap, ratio);}bitmap.Save(savePath, System.Drawing.Imaging.ImageFormat.Gif);bitmap.Dispose();logger.Debug("bitmap.Dispose();");logger.Debug("finish");}catch (Exception ex){logger.Info($"exception: {ex.Message}");}}private static Bitmap CutImage(Bitmap source, Rectangle p){// An empty bitmap which will hold the cropped imageBitmap bmp = new Bitmap(p.Width, p.Height);//using (Bitmap bmp = new Bitmap(p.Width, p.Height)){Graphics g = Graphics.FromImage(bmp);// Draw the given area (p) of the source image// at location 0,0 on the empty bitmap (bmp)g.DrawImage(source, 0, 0, p, GraphicsUnit.Pixel);return bmp;}}private static Bitmap Resize(Bitmap originImage, Double times){int width = Convert.ToInt32(originImage.Width * times);int height = Convert.ToInt32(originImage.Height * times);return ResizeProcess(originImage, originImage.Width, originImage.Height, width, height);}private static Bitmap ResizeProcess(Bitmap originImage, int oriwidth, int oriheight, int width, int height){Bitmap resizedbitmap = new Bitmap(width, height);//using (Bitmap resizedbitmap = new Bitmap(width, height)){Graphics g = Graphics.FromImage(resizedbitmap);g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;g.Clear(Color.Transparent);g.DrawImage(originImage, new Rectangle(0, 0, width, height), new Rectangle(0, 0, oriwidth, oriheight), GraphicsUnit.Pixel);return resizedbitmap;}}}class ScreenShotParam{public string Url { get; set; }public string SavePath { get; set; }public int Width { get; set; }public int Height { get; set; }public int Left { get; set; }public int Top { get; set; }/// <summary>/// 長邊縮到指定長度/// </summary>public int ResizeMaxWidth { get; set; }public bool Wait { get; set; }}}
效果
完成,达到预期的效果。