Convertir une page Web en image à partir d’ASP.NET

Je voudrais créer une fonction en C # qui prend une page Web spécifique et la couvre à une image JPG depuis ASP.NET. Je ne veux pas le faire via un service tiers ou une vignette car j’ai besoin de l’image complète. Je suppose que je devrais tirer parti du contrôle du navigateur Web depuis ASP.NET, mais je ne vois pas où commencer. Est-ce que quelqu’un a des exemples?

Ok, c’était plutôt facile quand j’ai combiné plusieurs solutions différentes:

Ces solutions m’ont permis d’utiliser WebBrowser depuis ASP.NET de manière sécurisée:

http://www.beansoftware.com/ASP.NET-Tutorials/Get-Web-Site-Thumbnail-Image.aspx

http://www.eggheadcafe.com/tutorials/aspnet/b7cce396-e2b3-42d7-9571-cdc4eb38f3c1/build-a-selfcaching-asp.aspx

Cette solution m’a permis de convertir BMP en JPG:

Bmp en jpg / png en C #

J’ai simplement adapté le code et mis le suivant dans un .cs:

using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Threading; using System.Windows.Forms; public class WebsiteToImage { private Bitmap m_Bitmap; private ssortingng m_Url; private ssortingng m_FileName = ssortingng.Empty; public WebsiteToImage(ssortingng url) { // Without file m_Url = url; } public WebsiteToImage(ssortingng url, ssortingng fileName) { // With file m_Url = url; m_FileName = fileName; } public Bitmap Generate() { // Thread var m_thread = new Thread(_Generate); m_thread.SetApartmentState(ApartmentState.STA); m_thread.Start(); m_thread.Join(); return m_Bitmap; } private void _Generate() { var browser = new WebBrowser { ScrollBarsEnabled = false }; 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) { // Capture var 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) { // Save m_Bitmap.SaveJPG100(m_FileName); } } } public static class BitmapExtensions { public static void SaveJPG100(this Bitmap bmp, ssortingng filename) { var encoderParameters = new EncoderParameters(1); encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L); bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters); } public static void SaveJPG100(this Bitmap bmp, Stream stream) { var encoderParameters = new EncoderParameters(1); encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L); bmp.Save(stream, GetEncoder(ImageFormat.Jpeg), encoderParameters); } public static ImageCodecInfo GetEncoder(ImageFormat format) { var codecs = ImageCodecInfo.GetImageDecoders(); foreach (var codec in codecs) { if (codec.FormatID == format.Guid) { return codec; } } // Return return null; } } 

Et peut l’appeler comme suit:

 WebsiteToImage websiteToImage = new WebsiteToImage( "http://www.cnn.com", @"C:\Some Folder\Test.jpg"); websiteToImage.Generate(); 

Il fonctionne avec un fichier et un stream. Assurez-vous d’append une référence à System.Windows.Forms à votre projet ASP.NET. J’espère que ça aide.

MISE À JOUR: J’ai mis à jour le code pour inclure la possibilité de capturer l’intégralité de la page et ne pas nécessiter de parameters spéciaux pour n’en capturer qu’une partie.

Voici mon implémentation utilisant des méthodes d’extension et une fabrique de tâches à la place du thread:

 ///  /// Convert url to bitmap byte array ///  /// Url to browse /// width of page (if page contains frame, you need to pass this params) /// heigth of page (if page contains frame, you need to pass this params) /// function to manipulate dom /// in milliseconds, how long can you wait for page response? /// bitmap byte[] ///  /// byte[] img = new Uri("http://www.uol.com.br").ToImage(); ///  public static byte[] ToImage(this Uri url, int? width = null, int? height = null, Action htmlToManipulate = null, int timeout = -1) { byte[] toReturn = null; Task tsk = Task.Factory.StartNew(() => { WebBrowser browser = new WebBrowser() { ScrollBarsEnabled = false }; browser.Navigate(url); browser.DocumentCompleted += (s, e) => { var browserSender = (WebBrowser)s; if (browserSender.ReadyState == WebBrowserReadyState.Complete) { if (htmlToManipulate != null) htmlToManipulate(browserSender.Document); browserSender.ClientSize = new Size(width ?? browser.Document.Body.ScrollRectangle.Width, height ?? browser.Document.Body.ScrollRectangle.Bottom); browserSender.ScrollBarsEnabled = false; browserSender.BringToFront(); using (Bitmap bmp = new Bitmap(browserSender.Document.Body.ScrollRectangle.Width, browserSender.Document.Body.ScrollRectangle.Bottom)) { browserSender.DrawToBitmap(bmp, browserSender.Bounds); toReturn = (byte[])new ImageConverter().ConvertTo(bmp, typeof(byte[])); } } }; while (browser.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); } browser.Dispose(); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); tsk.Wait(timeout); return toReturn; } 

Bonne solution par Mr Cat Man Do.

J’ai eu besoin d’append une ligne pour supprimer certaines erreurs qui sont apparues dans certaines pages Web (avec l’aide d’un collègue génial)

 private void _Generate() { var browser = new WebBrowser { ScrollBarsEnabled = false }; browser.ScriptErrorsSuppressed = true; // <-- browser.Navigate(m_Url); browser.DocumentCompleted += WebBrowser_DocumentCompleted; } 

...

Merci Mr Do

Il y a un bon article de Peter Bromberg sur ce sujet ici . Sa solution semble faire ce dont vous avez besoin …

Vous pouvez utiliser WatiN pour ouvrir un nouveau navigateur, puis capturer l’écran et le rogner correctement.

La solution est parfaite, il suffit d’une fixation dans la ligne qui définit la LARGEUR de l’image. Pour les pages avec une grande hauteur, il ne définit pas correctement la largeur:

  //browser.ClientSize = new Size(browser.Document.Body.ScrollRectangle.Width, browser.Document.Body.ScrollRectangle.Bottom); browser.ClientSize = new Size(1000, browser.Document.Body.ScrollRectangle.Bottom); 

Et pour append une référence à System.Windows.Forms, vous devez le faire dans l’onglet .NET d’ADD REFERENCE au lieu de COM -tab.