Blogger

  • This email address is being protected from spambots. You need JavaScript enabled to view it.

    Recent items

Login

Tuesday, 06 August 2013 11:25

How to create print screen of current page (or part of page) with SharePoint

Written by
Rate this item
(0 votes)

This is a brief description to how generate an image of a SharePoint aspx page (or part of page).

This is the main class that provide to generate an image starting from the aspx page

Show/Hidden csharp code

View source
 
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using Microsoft.SharePoint;
 
namespace lucacostante.com
{
    public class ASPXToImage
    {
        private Bitmap bitmap;
        private string url;
        private string fileName = string.Empty;
        private string startFromID = string.Empty;
        private Control control = null;
 
 
        public ASPXToImage(string url, string fileName)
        {
            this.url = url;
            this.fileName = fileName;
        }
 
        public Bitmap GenerateFull()
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
               {
                   using (SPSite site = new SPSite(this.url))
                   {
                       using (SPWeb w = site.OpenWeb())
                       {
                           // Thread 
                           var m_thread = new Thread(Generate);
                           m_thread.SetApartmentState(ApartmentState.STA);
                           m_thread.Start();
                           m_thread.Join();
                       }
                   }
               });
            return bitmap;
        }
 
 
 
        public Bitmap GeneratePagePart(string partIdOrClass)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
               {
                   using (SPSite site = new SPSite(this.url))
                   {
                       using (SPWeb w = site.OpenWeb())
                       {
                           this.startFromID = partIdOrClass;
 
                           // Thread 
                           var m_thread = new Thread(GeneratePart);
                           m_thread.SetApartmentState(ApartmentState.STA);
                           m_thread.Start();
                           m_thread.Join();
                       }
                   }
               });
            return bitmap;
 
        }
 
        private void Generate()
        {
            var browser = new WebBrowser { ScrollBarsEnabled = false };
            browser.Navigate(url);
            browser.DocumentCompleted += WebBrowser_FullDocumentCompleted;
 
            while (browser.ReadyState != WebBrowserReadyState.Complete)
            {
                Application.DoEvents();
            }
 
            browser.Dispose();
        }
 
        private void GeneratePart()
        {
            var browser = new WebBrowser { ScrollBarsEnabled = false };
            browser.Navigate(url);
            browser.DocumentCompleted += WebBrowser_PartDocumentCompleted;
 
            while (browser.ReadyState != WebBrowserReadyState.Complete)
            {
                Application.DoEvents();
            }
 
            browser.Dispose();
        }
 
        private void WebBrowser_FullDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // Capture 
            var browser = (WebBrowser)sender;
            int width = browser.Document.Body.ScrollRectangle.Width;
 
            int height = browser.Document.Body.ScrollRectangle.Bottom;
 
            GenerateImage(browser, width, height);
        }
 
        private void WebBrowser_PartDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // Capture 
            var browser = (WebBrowser)sender;
 
            HtmlElement found = FindIdOrClass(browser, startFromID);
 
            if (found != null)
            {
                GenerateImage(browser, found);
            }
        }
 
 
        private HtmlElement FindIdOrClass(WebBrowser browser, string startFromID)
        {
            HtmlElement found = null;
 
            found = (from HtmlElement ele in browser.Document.All
                     where ele.Id == startFromID ||
                     ele.GetAttribute("className") == startFromID
                     select ele).FirstOrDefault();
 
 
            return found;
        }
 
        private void GenerateImage(WebBrowser browser, int width, int height)
        {
            browser.ClientSize = new Size(width, height);
            browser.ScrollBarsEnabled = false;
            bitmap = new Bitmap(width, height);
            browser.BringToFront();
 
            browser.DrawToBitmap(bitmap, browser.Bounds);
 
            // Save as file? 
            if (this.fileName.Length > 0)
            {
                // Save 
                bitmap.SaveJPG100(this.fileName);
            }
        }
 
        private void GenerateImage(WebBrowser browser, HtmlElement ele)
        {
            Rectangle rec = ele.OffsetRectangle;
 
            int width = browser.Document.Body.ScrollRectangle.Width;
            int height = browser.Document.Body.ScrollRectangle.Bottom;
 
            CalculateSize(browser.Document.Body, ref width, ref height);
 
            int y = 0;
            int x = 0;
            int previewOffsetX = 0;
            int previewOffsetY = 0;
            HtmlElement parent = ele;
 
 
            while (parent != null)
            {
                if (parent.OffsetRectangle.Top != previewOffsetY)
                    y += parent.OffsetRectangle.Top;
                if (parent.OffsetRectangle.Left != previewOffsetX)
                    x += parent.OffsetRectangle.Left;
 
                previewOffsetX = parent.OffsetRectangle.Left;
                previewOffsetY = parent.OffsetRectangle.Top;
 
                parent = parent.Parent;
 
            }
            Rectangle rect = new Rectangle(x / 2, y, ele.OffsetRectangle.Width, ele.OffsetRectangle.Height);
 
            width = (ele.OffsetRectangle.Width + x > width) ? ele.OffsetRectangle.Width + x : width;
 
            browser.ClientSize = new Size(width, height);
 
            using (Bitmap bitmap = new Bitmap(browser.Width, browser.Height))
            {
                browser.DrawToBitmap(bitmap, new Rectangle(0, 0, browser.Width, browser.Height));
                Bitmap cropped = bitmap.Clone(rect, bitmap.PixelFormat);
                cropped.Save(this.fileName, ImageFormat.Jpeg);
            }
        }
 
        private void CalculateSize(HtmlElement currElement, ref int width, ref int height)
        {
            if (currElement.Children != null && currElement.Children.Count > 0)
            {
                foreach (HtmlElement element in currElement.Children)
                {
                    if (element.ScrollRectangle.Width > width)
                        width = element.ScrollRectangle.Width;
 
                    if (element.ScrollRectangle.Bottom > height)
                        height = element.ScrollRectangle.Bottom;
 
                    CalculateSize(element, ref width, ref height);
                }
            }
        }
 
    }
 
 
    public static class BitmapExtensions
    {
        public static void SaveJPG100(this Bitmap bmp, string 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;
        }
    }
}
 

In my case, after the page creation, I've uploaded the image into the Image document library and after I've redirect the user to its url.

This is the print screen:

When I click on "Generate Image" ribbon button, The syste create the image taking the information in a div with the id "previewBody".

This is the code to generate, upload and redirect to the generated image

Show/Hidden csharp code

View source
 
 
 
protected void GenerateImage()
        {
            string path = Environment.GetEnvironmentVariable("TEMP") + @"\" + (Guid.NewGuid().ToString("N"));
            ASPXToImage websiteToImage = new ASPXToImage(Request.Url.AbsoluteUri, path);
            websiteToImage.GeneratePagePart("previewBody");
 
            byte[] fileContents;
            SPSecurity.RunWithElevatedPrivileges(delegate()
             {
                  using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                   {
                       using (SPWeb web = site.OpenWeb())
                       {
                           if (System.IO.File.Exists(path))
                           {
                               SPList images = web.Webs["newsletter"].Lists["Images"];
 
                               bool successfully = false;
                               SPFile file;
                               using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
                               {
                                   int length = (int)fileStream.Length;  // get file length
                                   fileContents = new byte[length];            // create buffer
                                   int count;                            // actual number of bytes read
                                   int sum = 0;                          // total number of bytes read
 
 
                                   // read until Read method returns 0 (end of the stream has been reached)
                                   while ((count = fileStream.Read(fileContents, sum, length - sum)) > 0)
                                       sum += count;  // sum is a buffer offset for next reading
 
                                   images.ParentWeb.AllowUnsafeUpdates = true;
 
 
                                   file = images.RootFolder.Files.Add(Guid.NewGuid().ToString("N") + ".jpg", fileContents, true);
 
                                   images.ParentWeb.AllowUnsafeUpdates = false;
 
                                   if (file != null)
                                   {
                                       successfully = true;
                                   }
                               }
                               if (successfully)
                               {
                                   System.IO.File.Delete(path);
                                   Response.Redirect(SPContext.Current.Web.Url + "/" + file.Url);
                               }
                           }
                       }
                 }
             });
        }
 
 
 

This is the result

Note: During the deploy in production, this feature does not work because it need the credentials and the WebBrowser does not allow the NTLM access (infact it loops into while cicle).

To  resolve the problem, there are two possible solution:

  1. Allow Basic authentication and pass the credentials to the WebBrowser object
  2. extend the WebApplication with an anonymous zone. Allow the navigation of this zone only into the current server. put the logic that the image will be generated into the anonymous zone.

 

Read 13327 times Last modified on Tuesday, 12 January 2016 10:33

Leave a comment

Make sure you enter all the required information, indicated by an asterisk (*). HTML code is not allowed.