Click here to Skip to main content
Click here to Skip to main content

Get ASP.NET C# 2.0 Website Thumbnail Screenshot

By , 22 Jul 2010
 

screenshot.JPG

Sample application screenshot

Introduction

This sample code/website gets the thumbnail/screenshot for a specific URL, giving the browser dimensions and the thumbnail dimensions you want.

Background

Well, tired of search for a method for giving me the screenshot of a URL, and just finding examples of Windows.Forms, with the simple method DrawToBitmap, I just realized that in ASP.NET, that does not work like that, because of Single Thread and Multi Thread; so I used .SetApartmentState(ApartmentState.STA) to make it single threaded.

Using the Code

Just call the method that you want to associate with the ImageUrl of an ASP.NET Image control.

Server-side

Calling with the IHttpHandler Method

ImageBox.ImageUrl = "~/HandlerWSThumb.ashx?url=" + 
   Server.UrlEncode(txtURL.Text).ToLower().ToString() + "&bw=" + 
   txtBW.Text + "&bh=" + txtBH.Text + "&tw=" + 
   txtTW.Text + "&th=" + txtTH.Text;

Calling with the Class Method

Bitmap bmp = ClassWSThumb.GetWebSiteThumbnail(txtURL.Text, Int32.Parse(txtBW.Text), 
             Int32.Parse(txtBH.Text), Int32.Parse(txtTW.Text), 
             Int32.Parse(txtTH.Text));
bmp.Save(Server.MapPath("~") + "/thumbnail.bmp");
ImageBox.ImageUrl = "~/thumbnail.bmp";

//**if Jpeg is the image format you need just replace the 2 lines above for:
//
//bmp.Save(Server.MapPath("~") + "/thumbnail.jpg", ImageFormat.Jpeg);
//ImageBox.ImageUrl = "~/thumbnail.jpg";

//** but don't forget to add the reference
//   to the class in the page 'Default.aspx'(code behind):
//using System.Drawing.Imaging;

Here is the class method code:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.IO;

namespace GetWebSiteThumb
{
    public class ClassWSThumb
    {
        public static Bitmap GetWebSiteThumbnail(string Url, int BrowserWidth, 
               int BrowserHeight, int ThumbnailWidth, int ThumbnailHeight)
        {
            return new WSThumb(Url, BrowserWidth, BrowserHeight, 
                   ThumbnailWidth, ThumbnailHeight).GetWSThumb();
        }

        private class WSThumb
        {
            public WSThumb(string Url, int BW, int BH, int TW, int TH) {
                __Url = Url;
                __BrowserWidth = BW;
                __BrowserHeight = BH;
                __ThumbnailWidth = TW;
                __ThumbnailHeight = TH;
            }

            private Bitmap __Bitmap = null;            
            private string __Url = null;
            private int __ThumbnailWidth;
            private int __ThumbnailHeight;
            private int __BrowserWidth;
            private int __BrowserHeight;

            public string Url            {
                get{return __Url;}
                set{__Url = value;}
            }
            
            public Bitmap ThumbnailImage            {
                get{return __Bitmap;}
            }

            public int ThumbnailWidth            {
                get{return __ThumbnailWidth;}
                set{__ThumbnailWidth = value;}
            }

            public int ThumbnailHeight            {
                get {return __ThumbnailHeight;}
                set {__ThumbnailHeight = value;}
            }

            public int BrowserWidth            {
                get{return __BrowserWidth;}
                set{__BrowserWidth = value;}
            }

            public int BrowserHeight            {
                get{return __BrowserHeight;}
                set{__BrowserHeight = value;}
            }

            public Bitmap GetWSThumb()            {
                ThreadStart __threadStart = new ThreadStart(_GenerateWSThumb);
                Thread __thread = new Thread(__threadStart);

                __thread.SetApartmentState(ApartmentState.STA);
                __thread.Start();
                __thread.Join();
                return __Bitmap;
            }

            private void _GenerateWSThumb()            {
                WebBrowser __WebBrowser = new WebBrowser();
                __WebBrowser.ScrollBarsEnabled = false;
                __WebBrowser.Navigate(__Url);
                __WebBrowser.DocumentCompleted += 
                  new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
                while (__WebBrowser.ReadyState != WebBrowserReadyState.Complete)
                    Application.DoEvents();
                __WebBrowser.Dispose();
            }

            private void WebBrowser_DocumentCompleted(object sender, 
                         WebBrowserDocumentCompletedEventArgs e)            {
                WebBrowser __WebBrowser = (WebBrowser)sender;
                __WebBrowser.ClientSize = new Size(this.__BrowserWidth, this.__BrowserHeight);
                __WebBrowser.ScrollBarsEnabled = false;
                __Bitmap = new Bitmap(__WebBrowser.Bounds.Width, __WebBrowser.Bounds.Height);
                __WebBrowser.BringToFront();
                __WebBrowser.DrawToBitmap(__Bitmap, __WebBrowser.Bounds);
                
                if (__ThumbnailHeight != 0 && __ThumbnailWidth !=0)
                __Bitmap = (Bitmap)__Bitmap.GetThumbnailImage(
                    __ThumbnailWidth, __ThumbnailHeight, null, IntPtr.Zero);                
            }
        }
    }
}

Here is the IHTTPHandler method code:

using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Reflection;

namespace GetWebSiteThumb
{
    /// <summary>
    /// Summary description for $codebehindclassname$
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class HandlerWSThumb : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            Bitmap thumb = null;
            string url = null;
            int bw = 800; //valor por defeito
            int bh = 600; //valor por defeito
            int tw = 0;    // sem thumbnail 
            int th = 0;

            context.Response.ContentType = "image/jpeg";
            if (context.Request["url"] != null)
            {
                if (context.Request["url"].ToString().ToLower().Contains("http://") || 
                       context.Request["url"].ToString().ToLower().Contains("https://"))
                    url = context.Request["url"].ToString();
                else
                    url = "http://" + context.Request["url"].ToString();
            }

            if (context.Request["bw"] != null)
                bw = Int32.Parse(context.Request["bw"].ToString());

            if (context.Request["bh"] != null)
                bh = Int32.Parse(context.Request["bh"].ToString());

            if (context.Request["tw"] != null)
                tw = Int32.Parse(context.Request["tw"].ToString());

            if (context.Request["th"] != null)
                th = Int32.Parse(context.Request["th"].ToString());

            // return context bitmap
            thumb = GetWebSiteThumbnail(url, bw, bh);

            if (tw != 0 && th != 0)
                thumb.GetThumbnailImage(tw, th, null, IntPtr.Zero).Save(
                           context.Response.OutputStream, ImageFormat.Jpeg);
            else
                thumb.Save(context.Response.OutputStream, ImageFormat.Jpeg);

            thumb.Dispose();
        }

        public static Bitmap GetWebSiteThumbnail(string Url, 
                      int BrowserWidth, int BrowserHeight)
        {
            WebsiteThumbnailImage thumbnailGenerator = 
              new WebsiteThumbnailImage(Url, BrowserWidth, BrowserHeight);
            return thumbnailGenerator.GenerateWebSiteThumbnailImage();
        }

        private class WebsiteThumbnailImage
        {
            public WebsiteThumbnailImage(string Url, 
                   int BrowserWidth, int BrowserHeight)
            {
                this.m_Url = Url;
                this.m_BrowserWidth = BrowserWidth;
                this.m_BrowserHeight = BrowserHeight;
            }

            private string m_Url = null;
            public string Url
            {
                get { return m_Url; }
                set { m_Url = value; }
            }

            private Bitmap m_Bitmap = null;
            public Bitmap ThumbnailImage
            {
                get { return m_Bitmap; }
            }

            private int m_BrowserWidth;
            public int BrowserWidth
            {
                get { return m_BrowserWidth; }
                set { m_BrowserWidth = value; }
            }

            private int m_BrowserHeight;
            public int BrowserHeight
            {
                get { return m_BrowserHeight; }
                set { m_BrowserHeight = value; }
            }

            public Bitmap GenerateWebSiteThumbnailImage()
            {
                Thread m_thread = 
                  new Thread(new ThreadStart(_GenerateWebSiteThumbnailImage));
                m_thread.SetApartmentState(ApartmentState.STA);
                m_thread.Start();
                m_thread.Join();
                return m_Bitmap;
            }

            private void _GenerateWebSiteThumbnailImage()
            {
                WebBrowser m_WebBrowser = new WebBrowser();
                m_WebBrowser.ScrollBarsEnabled = false;
                m_WebBrowser.Navigate(m_Url);
                m_WebBrowser.DocumentCompleted += 
                  new WebBrowserDocumentCompletedEventHandler(
                  WebBrowser_DocumentCompleted);
                while (m_WebBrowser.ReadyState != WebBrowserReadyState.Complete)
                    Application.DoEvents();
                m_WebBrowser.Dispose();
            }

            private void WebBrowser_DocumentCompleted(object sender, 
                    WebBrowserDocumentCompletedEventArgs e)
            {
                WebBrowser m_WebBrowser = (WebBrowser)sender;
                m_WebBrowser.ClientSize = new Size(this.m_BrowserWidth, 
                                          this.m_BrowserHeight);
                m_WebBrowser.ScrollBarsEnabled = false;
                m_Bitmap = new Bitmap(m_WebBrowser.Bounds.Width, 
                                      m_WebBrowser.Bounds.Height);
                m_WebBrowser.BringToFront();
                m_WebBrowser.DrawToBitmap(m_Bitmap, m_WebBrowser.Bounds);
                //m_Bitmap = (Bitmap)m_Bitmap.GetThumbnailImage(
                //   m_ThumbnailWidth, m_ThumbnailHeight, null, IntPtr.Zero);
            }
        }

        // Resusable flag
        public bool IsReusable
        {
            get { return false; }
        }
    }
}

Points of Interest

I learn that there are always three ways to do things: the right way, the wrong way, and the best way. I tried to cover the 3 of them ;) As an add-on, you could build a WebService method for returning the thumbnail. Maybe I will edit this article in the near future and put some code in the sample to accomplish it.

History

  • Version 1.0: Upgrades and tips are welcome.
  • Version 1.1: Just added a comment about converting the resulting BMP in the class method to JPEG, after a user asked me to do that.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Gilberto Francisco
Web Developer Microsky
Portugal Portugal
Software developer since 1986, as a hobby
and since 1998 as a professional
 
Currently working for Ogilvy S.A.
(Advertinsing media in portugal)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 3memberref99715-Jan-13 2:24 
sdgdfgdfg
GeneralMy vote of 5memberSavalia Manoj M30-Dec-12 21:52 
Excellent work....
Questionwant to capture entire webpage with scrollbarmemberGaurav Mishra29-Nov-12 2:54 
I want to capture entire page is it possible?
AnswerRe: want to capture entire webpage with scrollbarmemberGilberto Francisco29-Nov-12 3:37 
I think this sample already does that ....
Questionnot working for dynamic webpagesmemberroopali@241127-Aug-12 3:30 
this code is working well for static webpages like google.com and gmail.com but not for yahoo.com and other dynamic webpages
NewsWorks well, Vote 5memberDadajiIn15-Jun-12 0:30 
Hello, thanks your code works very well, our company used it here in a project http://www.dotnetfiles.com/Control/4/websnap.aspx[^]
Suggestionsome suggestionsmemberMember 43531606-Apr-12 0:56 
To suppress Javascript errors add this line in _GenerateWSThumb:
__WebBrowser.ScriptErrorsSuppressed = true;
 
Also there should be a loading time limit for a website. My solution for this was
to set an execution timeout for the thread in GetWSThumb:
 
__thread.Join(10000);

QuestionAwesome articlememberTanzeelurRehman13-Mar-12 7:59 
I was searching for this article for hours. Thanks.
 
Awesome and superb article
GeneralI managed to convert the class ClassWSThumb in vb.net. and the usage of it in any click button event [modified]membertemhz14-Dec-11 6:33 
The class ClassWSThumb
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Threading
Imports System.IO
 
Namespace GetWebSiteThumb
    Public Class ClassWSThumb
        Public Shared Function GetWebSiteThumbnail(ByVal Url As String, ByVal BrowserWidth As Integer, ByVal BrowserHeight As Integer, ByVal ThumbnailWidth As Integer, ByVal ThumbnailHeight As Integer) As Bitmap
            Return New WSThumb(Url, BrowserWidth, BrowserHeight, ThumbnailWidth, ThumbnailHeight).GetWSThumb()
        End Function
 
        Private Class WSThumb
            Public Sub New(ByVal Url As String, ByVal BW As Integer, ByVal BH As Integer, ByVal TW As Integer, ByVal TH As Integer)
                __Url = Url
                __BrowserWidth = BW
                __BrowserHeight = BH
                __ThumbnailWidth = TW
                __ThumbnailHeight = TH
            End Sub
 
            Private __Bitmap As Bitmap = Nothing
            Private __Url As String = Nothing
            Private __ThumbnailWidth As Integer
            Private __ThumbnailHeight As Integer
            Private __BrowserWidth As Integer
            Private __BrowserHeight As Integer
 
            Public Property Url() As String
                Get
                    Return __Url
                End Get
                Set(ByVal value As String)
                    __Url = value
                End Set
            End Property
 
            Public ReadOnly Property ThumbnailImage() As Bitmap
                Get
                    Return __Bitmap
                End Get
            End Property
 
            Public Property ThumbnailWidth() As Integer
                Get
                    Return __ThumbnailWidth
                End Get
                Set(ByVal value As Integer)
                    __ThumbnailWidth = value
                End Set
            End Property
 
            Public Property ThumbnailHeight() As Integer
                Get
                    Return __ThumbnailHeight
                End Get
                Set(ByVal value As Integer)
                    __ThumbnailHeight = value
                End Set
            End Property
 
            Public Property BrowserWidth() As Integer
                Get
                    Return __BrowserWidth
                End Get
                Set(ByVal value As Integer)
                    __BrowserWidth = value
                End Set
            End Property
 
            Public Property BrowserHeight() As Integer
                Get
                    Return __BrowserHeight
                End Get
                Set(ByVal value As Integer)
                    __BrowserHeight = value
                End Set
            End Property
 
            Public Function GetWSThumb() As Bitmap
                Dim __threadStart As New ThreadStart(AddressOf _GenerateWSThumb)
                Dim __thread As New Thread(__threadStart)
 
                __thread.SetApartmentState(ApartmentState.STA)
                __thread.Start()
                __thread.Join()
                Return __Bitmap
            End Function
 
            Private Sub _GenerateWSThumb()
                Dim __WebBrowser As New WebBrowser()
                __WebBrowser.ScrollBarsEnabled = False
                __WebBrowser.Navigate(__Url)
                AddHandler __WebBrowser.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf WebBrowser_DocumentCompleted)
                While __WebBrowser.ReadyState <> WebBrowserReadyState.Complete
                    Application.DoEvents()
                End While
                __WebBrowser.Dispose()
            End Sub
 
            Private Sub WebBrowser_DocumentCompleted(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs)
                Dim __WebBrowser As WebBrowser = DirectCast(sender, WebBrowser)
                __WebBrowser.ClientSize = New Size(Me.__BrowserWidth, Me.__BrowserHeight)
                __WebBrowser.ScrollBarsEnabled = False
                __Bitmap = New Bitmap(__WebBrowser.Bounds.Width, __WebBrowser.Bounds.Height)
                __WebBrowser.BringToFront()
                __WebBrowser.DrawToBitmap(__Bitmap, __WebBrowser.Bounds)
 
                If __ThumbnailHeight <> 0 AndAlso __ThumbnailWidth <> 0 Then
                    __Bitmap = DirectCast(__Bitmap.GetThumbnailImage(__ThumbnailWidth, __ThumbnailHeight, Nothing, IntPtr.Zero), Bitmap)
                End If
            End Sub
        End Class
    End Class
End Namespace
In your sample.aspx were you have for example the click button to execute the class
Import those two libraries
 
Imports System.Drawing
Imports GetWebSiteThumb
 
add the two methods
Protected Sub StartDuration()
      begintime = DateTime.Now
  End Sub
 
  Protected Sub StopDuration()
      stoptime = DateTime.Now
      Dim duration As TimeSpan = (stoptime - begintime)
      'lblTime.Text = duration.ToString()
  End Sub
 
and this is the click event
 
Protected Sub btnExportTositetoimg_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnExportTositetoimg_Click.Click
StartDuration()
       Dim url As String = "http://templates.codecraftshop.gr"
 
       'example as a Class Method
       Dim bmp As Bitmap = ClassWSThumb.GetWebSiteThumbnail(url, Int32.Parse(800), Int32.Parse(600), Int32.Parse(800), Int32.Parse(600))
       bmp.Save(Server.MapPath("~") + "/thumbnail.bmp")
       'ImageBox.ImageUrl = "~/thumbnail.bmp"
       Image1.ImageUrl = "~/thumbnail.bmp"
 
       StopDuration()
 End Sub


modified 15-Dec-11 5:31am.

QuestionIt can't change the Image name . [modified]memberHatef Ghaniyarlou10-Aug-11 4:49 
I Used this code :
 
string  GuidedName = Guid.NewGuid();
            bmp.Save(Server.MapPath("~") + "/"  + GuidedName, ImageFormat.Jpeg);
            ImageBox.ImageUrl = "~/"  + GuidedName;
 
or
 
string  GuidedName = Guid.NewGuid();
            bmp.Save(Server.MapPath("~") + "/"  + GuidedName+"jpg", ImageFormat.Jpeg);
            ImageBox.ImageUrl = "~/"  + GuidedName+"jpg";
 

and I use your own code that you said in article but it's not working .
 
it can't generate .jpeg file .

modified on Wednesday, August 10, 2011 11:03 AM

AnswerRe: It can't change the Image name . [modified]membermoshman0811-Nov-11 7:52 
Hi, i see 2 possible errors, first, you need to do Guid.NewGuid().toString().
the second problem, is probably that you are missing de dot "." , before the "jpg".
 
Hope it helps
GeneralMy publish code not workingmemberNibeditaJena13-Apr-11 1:18 
Hi, I have used your class file. Its working fine locally. But its not working after deployment. It showing Action Canceled.
Could you plz help me?
 

Thanks & regards
Nibedita Jena
QuestionVB.net ?memberMember 777093220-Mar-11 20:25 
Hi,
 
Is it possible that your code can work in VB.net? My website application is in this language. I tried converting a similar program to this written in C#. I got error messages for the webbrowser control. I guess you can't really use windows.forms in vb.net in the imports area. I need .jpg files for my site. I saw your comment for this.
 
Thanks,
 
Scot King
Developer
http://www.zlinkexchange.com
Generaldoes not workmemberOmar Gamil14-Mar-11 3:12 
both methods wont work
GeneralRe: does not workmemberGilberto Francisco14-Mar-11 4:55 
did u add the reference to the project?
are you using windows forms or WEB?
please specify more about the problem.
 
Thanks
GeneralRe: does not workmemberOmar Gamil14-Mar-11 4:59 
i downloaded the source code you provided (in the link above)
unzipped it
compiled and built successfully, but it just doesn't work, i press the buttons and nothing happens.
GeneralRe: does not workmemberGilberto Francisco14-Mar-11 5:05 
Check with another browser ... google Chrome , Firefox.
 
Do you have a URL written in the box with "http://www"
 
ex: "http://www.google.com"
GeneralRe: does not workmemberOmar Gamil14-Mar-11 5:07 
i tried with firefox and IE 8
and Yes there is the default URL you wrote http://www.codeproject.com
GeneralRe: does not workmemberGilberto Francisco14-Mar-11 5:44 
so .. what do you expect to happen? ... do you understand what the buttons do?
the buttons return the screenshot of the URL you written in the box...
 
do you see the thumbnail of codeproject web site?
if you modify the url and put http://www.google.com
and press the buttons do you see the screenshot of google ?
GeneralRe: does not workmemberOmar Gamil14-Mar-11 9:22 
Gilberto Francisco wrote:
so .. what do you expect to happen? ... do you understand what the buttons do?

 

Are you serious ? Smile | :) even if i haven't read the entire article at least i would have noticed the title Big Grin | :-D
plus im a programmer too you know!
 
anyway i haven't tried with a different URL, i just ran it as-is.
i'll give it another shot later.
Generalportabilitymemberabhishek_mys0524-Jan-11 20:05 
hi, this code works fine for me in local, but its not working in godaddy, so please help me:(
GeneralRe: portabilitymemberGilberto Francisco14-Mar-11 4:56 
it has to work in godaddy too...
chekc if the all the library exists both in your localhost and godaddy ...(/bin)
GeneralMy vote of 4memberwindmove12-Jan-11 11:16 
the Idea of taking screen shots online is interesting!
QuestionHow can this be a Website?membernige*30-Nov-10 15:42 
How can this be run as a website when it uses Systems.Forms.Windows, __WebBrowser = new WebBrowser() and Application.DoEvents(), none of which are allowed in a website application? Thumbs Down | :thumbsdown:
I've copied the code into my Visual Studio 2008 VB.NET website and it won't compile. Cry | :((
AnswerRe: How can this be a Website?memberMohamad4love5-Jun-11 23:40 
Just try to add reference for the System.windows.Forms
and it will works successfully
but the problem is not there the thread is more slower than our machines

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130619.1 | Last Updated 22 Jul 2010
Article Copyright 2010 by Gilberto Francisco
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid