This article will demonstrate you about how to create thumbnail image from live Microsoft Office Documents and PDF documents.

 

 

Currently I got the chance to create thumbnail images from live URL and these URL will not be images, it will be of some DOCX file, some XLSX file or PDF file. We don’t have any custom library which can directly generate the thumbnail from live URL. So, here we will learn how we can customize our code to generate thumbnail in .NET.

 

Getting thumbnail from Images are not very tough task, we can directly convert our image to Bitmap type and generate thumbnail. So, it’s very simple and lots of article are available on the Internet.

 

But getting thumbnail from live URL (Docx, Xlsx and Pdf) is not tough but tricky. We have to do couple of extra effort to complete thumbnail generation from these URLs.

 

For this demonstration, I am going to use Asp.Net MVC project and we are going to create thumbnail from Microsoft Office Documents and PDF as well and these documents can be Microsoft Word Document or Microsoft Excel Worksheets or even PDF also.

 

To create new project, just follow the following instructions.

  1. Open Visual Studio 2013/2015/2017
  2. Go to File menu and choose New and then Project.
  3. From New Project window, select “Asp.Net Web Application”
  4. Browse the location to save the project and provide suitable name and click to OK.
  5. From next window select MVC as a template and click to OK.

Project is ready for demonstration. To generate thumbnail from live URL, we will follow the following instruction.

  1. Download file in PDF format on temp location
  2. Convert PDF file to Bitmap image
  3. Generate thumbnail as Bitmap from Original Bitmap image.
  4. Save it to preferred location
  5. To show on View, Convert it to Base64String and Bind with Img tag.

So, above as we have defined couple of things which need to be completed to generate thumbnail from live URL and Save it to any location or show it on the View.

It’s very easy to convert a PDF file to image rather than converting any Microsoft Office file. So, here we first download these files on temporary location and then convert it to PDF forms. Once PDF will available then we can generate image from that.

If you will try to convert Microsoft Office files into PDF directly without Microsoft.Office.Interop then it will be corrupted and thumbnail will not be generated. So, basically we cannot directly convert live URL content to Bytes or Stream. So, to do that we have to generate PDF and perform thumbnail task.

Here we are going to generate thumbnail from three different types of file and these are DOCX, XLSX and PDF. To download and generate PDF from DOCX and XLSX, we will use the “Microsoft.Office.Interop”.

 

 

Following is the class name as “TypeConversion” which will help us to download and convert the file type from DOCX, XLSX to PDF on temporary location from live URL.

using System;
using Word = Microsoft.Office.Interop.Word;
using Excel = Microsoft.Office.Interop.Excel;
using System.IO;
using System.Net;

namespace GenerateThumbnails.Conversion
{
    public class TypeConversion 
    {
        private string _tempLocation = Path.GetPathRoot(Environment.SystemDirectory) + "WBTemp";

        Word.Application wordApp = null;
        Word.Documents wdDocuments = null;
        Word.Document wdDocument = null;

        Excel.Application excelApp = null;
        Excel.Workbooks xlBooks = null;
        Excel.Workbook xlBook = null;

        public bool WordToPdf(string _sourcePath, out string _outputTempFilePath)
        {
            wordApp = new Word.Application();
            wdDocuments = wordApp.Documents;

            try
            {
                //Read word document file
                wdDocument = wdDocuments.Open(_sourcePath);

                _outputTempFilePath = string.Empty;

                if (wdDocument != null)
                {
                    _outputTempFilePath = GetTempTargetFilePath(_tempLocation);

                    //Export word document file to pdf format
                    wdDocument.ExportAsFixedFormat(_outputTempFilePath, Word.WdExportFormat.wdExportFormatPDF);                  

                    return true;
                }
            }
            catch (Exception ex)
            {
                _outputTempFilePath = string.Empty;

                return false;
            }
            finally
            {
                // Cleanup
                GC.Collect();
                GC.WaitForPendingFinalizers();

                wdDocument.Close(false);
                NAR(wdDocument);
                NAR(wdDocuments);
                wordApp.Quit();
                NAR(wordApp);
            }

            return false;
        }

        public bool ExcelToPdf(string _sourcePath, out string _outputTempFilePath)
        {
            excelApp = new Excel.Application();

            try
            {
                //Read word document file
                xlBooks = excelApp.Workbooks;
                xlBook = xlBooks.Open(_sourcePath);

                _outputTempFilePath = string.Empty;

                if (xlBook != null)
                {
                    _outputTempFilePath = GetTempTargetFilePath(_tempLocation);

                    //Export word document file to pdf format
                    xlBook.ExportAsFixedFormat(Excel.XlFixedFormatType.xlTypePDF, _outputTempFilePath);

                    return true;
                }
            }
            catch (Exception ex)
            {
                _outputTempFilePath = string.Empty;

                return false;
            }
            finally
            {
                // Cleanup
                GC.Collect();
                GC.WaitForPendingFinalizers();

                xlBook.Close(false);
                NAR(xlBook);
                NAR(xlBooks);
                excelApp.Quit();
                NAR(excelApp);                
            }

            return false;
        }

        public bool PdfURLToPdf(string _sourcePath, out string _outputTempFilePath)
        {
            using(var client = new WebClient())
            {
                _outputTempFilePath = GetTempTargetFilePath(_tempLocation);
                client.DownloadFile(_sourcePath, _outputTempFilePath);
                return true;
            }
        }

        private void NAR(object o)
        {
            try
            {
                while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;
            }
            catch { }
            finally
            {
                o = null;
            }
        }

        public static string GetTempTargetFilePath(string _targetTempPath)
        {
            string _tempFilePath = string.Empty;

            //Check temp directory exists or not
            if (!Directory.Exists(_targetTempPath))
            {
                //Create new temp directory 
                Directory.CreateDirectory(_targetTempPath);
            }

            var _fileName = "temp.pdf";
            _tempFilePath = _targetTempPath + "/" + _fileName;

            if (File.Exists(_tempFilePath))
            {
                File.Delete(_tempFilePath);
            }
            return _tempFilePath;
        }
    }
}

 

As you can see here, in following class we have three methods which are WordToPdf, ExcelToPdf and PdfURLtoPdf. These methods basically take two parameters as source path and output temp path.  The source path is basically live URL of the documents and the temp path where PDF has generated on temporary location.

 

To create temp location, first we are creating a temporary folder using following code.

private string _tempLocation = Path.GetPathRoot(Environment.SystemDirectory) + "WBTemp";

 

And before downloading the file on this location we should check folder location exists or not. If the folder doesn’t exist, then it should be created.

public static string GetTempTargetFilePath(string _targetTempPath)
{
            string _tempFilePath = string.Empty;

            //Check temp directory exists or not
            if (!Directory.Exists(_targetTempPath))
            {
                //Create new temp directory 
                Directory.CreateDirectory(_targetTempPath);
            }

            var _fileName = "temp.pdf";
            _tempFilePath = _targetTempPath + "/" + _fileName;

            if (File.Exists(_tempFilePath))
            {
                File.Delete(_tempFilePath);
            }
            return _tempFilePath;
}

For Microsoft Word document, we should first open document and then export it to PDF format as following.

//Export word document file to pdf format

wdDocument.ExportAsFixedFormat(_outputTempFilePath, Word.WdExportFormat.wdExportFormatPDF);                  

And for Microsoft Excel, we should open workbook of excel document and then export it to PDF format.

NOTE: Be careful when using Microsoft.Office.Interop COM components because it generate memory overhead. So, leaving the method, be sure you have dispose non-required COM component instance as we are doing in Finally block.

We should release all the memory object till all referenced COM component is being disposed as following. This is best practice and it’s recommended by Microsoft guideline.

private void NAR(object o)
{
      try
      {
        while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;
      }
      catch { }
      finally
      {
         o = null;
      }
}
NOTE: When using COM component, always follow the rule “don’t use double dots”.

 

To download live PDF file, we are using WebClient which has a method as “DownloadFile” which takes two parameters first one is source live path and other where file will be downloaded. Here we don’t need any file type conversion because of we are working on the PDF itself to convert it to Bitmap for thumbnail generation.

NOTE: Using WebClient, we can download any type of file in the same format.

So, above we are done to convert our live URL of DOCX, XLSX and PDF to local file as a PDF. Now we can move to Generate thumbnail from temp PDF file.

Now we have PDF file which is saved locally at temp location. To generate thumbnail from these PDF files, we have created one more class as “Thumbnails” which has a method “GetThumbnail” which takes source path of temporary saved PDF file and returns Bitmap image as thumbnail. Here we are using default width and height of the thumbnail image as 150 and 180 respectively. You can customize this code and pass width and height as a parameter.

In this method, first we are generating an original Bitmap image from temporary PDF file and then resize and compress to export thumbnail based on Image size.

 

To directly generating the Bitmap from PDF file as an original image, we are using “Microsoft.WindowsAPICodePack.Shell.ShellFile” which takes source path of PDF and return output as Bitmap image. Following is the whole source code for the thumbnail class.

using Microsoft.WindowsAPICodePack.Shell;
using System;
using System.IO;
using System.Drawing;

namespace GenerateThumbnails.Conversion
{
    public class Thumbnails
    {       

        public Bitmap GetThumbnail(string _sourcePath)
        {
            const int bmpW = 150;
            const int bmpH = 180;
            Bitmap upBmp = null;

            if (!string.IsNullOrEmpty(_sourcePath))
            {
                if (Path.GetExtension(_sourcePath).ToLower() == ".pdf")
                {
                    ShellFile shellFile = ShellFile.FromFilePath(_sourcePath);
                    upBmp = shellFile.Thumbnail.ExtraLargeBitmap;
                }
            }

            if (upBmp != null)
            {
                Int32 newWidth = bmpW;
                Int32 newHeight = bmpH;

                Bitmap newBmp = new Bitmap(newWidth, newHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

                newBmp.SetResolution(72, 72);
                Double upWidth = upBmp.Width;
                Double upHeight = upBmp.Height;

                int newX = 0;
                int newY = 0;
                Double reDuce;
                if (upWidth > upHeight)
                {
                    reDuce = newWidth / upWidth;
                    newHeight = ((Int32)(upHeight * reDuce));
                    newY = ((Int32)((bmpH - newHeight) / 2));
                    newX = 0;
                }
                else if (upWidth < upHeight)
                {
                    reDuce = newHeight / upHeight;
                    newWidth = ((Int32)(upWidth * reDuce));
                    newX = ((Int32)((bmpW - newWidth) / 2));
                    newY = 0;
                }
                else if (upWidth == upHeight)
                {
                    reDuce = newHeight / upHeight;
                    newWidth = ((Int32)(upWidth * reDuce));
                    newX = ((Int32)((bmpW - newWidth) / 2));
                    newY = ((Int32)((bmpH - newHeight) / 2));
                }
                Graphics newGraphic = Graphics.FromImage(newBmp);
                try
                {
                    newGraphic.Clear(Color.White);
                    newGraphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    newGraphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    newGraphic.DrawImage(upBmp, newX, newY, newWidth, newHeight);
                    return newBmp;
                }
                catch (Exception ex)
                {
                    string newError = ex.Message;
                    // lblError.Text = newError;
                }
                finally
                {
                    upBmp.Dispose();
                   // newBmp.Dispose();
                    newGraphic.Dispose();
                }

              
            }

            return upBmp;
        }

        public void SavethumbnailToImage(Bitmap _bitmapImage, string _imagePath, string _typeOfImage)
        {
            if (_typeOfImage == "JPEG")
                _bitmapImage.Save(_imagePath, System.Drawing.Imaging.ImageFormat.Jpeg);
            else
                _bitmapImage.Save(_imagePath, System.Drawing.Imaging.ImageFormat.Png);
        }
    }
}

Once thumbnail is being generated, we can do two things. Either we can save it in any preferred location or directly shows on browser. Here we are doing both task.

First saving the thumbnail image on preferred location as following code shows and then removing the original temporary PDF file.

if (!string.IsNullOrEmpty(tempPath))
{
 if (bitmapThumb != null)
 {
  thumbnail.SavethumbnailToImage(bitmapThumb, Path.GetPathRoot(Environment.SystemDirectory) + "WBTemp/" + DateTime.Now.Date.Day.ToString() + DateTime.Now.Date.Month.ToString() + DateTime.Now.Date.Year + DateTime.Now.Date.Hour + DateTime.Now.Date.Minute + DateTime.Now.Date.Second + ".jpef", "JPEG");
 }
 
 if (System.IO.File.Exists(tempPath))
 {
  System.IO.File.Delete(tempPath);
 }
}

Saving can be done in any format, for this demonstration we have created following method which saves the Bitmap image to JPEG or PNG format

public void SavethumbnailToImage(Bitmap _bitmapImage, string _imagePath, string _typeOfImage)
{
            if (_typeOfImage == "JPEG")
                _bitmapImage.Save(_imagePath, System.Drawing.Imaging.ImageFormat.Jpeg);
            else
                _bitmapImage.Save(_imagePath, System.Drawing.Imaging.ImageFormat.Png);
}

Now it’s time to show the thumbnail image on View. So, to do this we will first convert thumbnail to Byte array and then convert it to Base64String that can be rendered on View.

MemoryStream ms = new MemoryStream();
bitmapThumb.Save(ms, ImageFormat.Jpeg);
byte[] bmpBytes = ms.ToArray();
string base64String = Convert.ToBase64String(bmpBytes);

ViewBag.Image = base64String;
return View();

Following is the whole source code for the HomeController.cs where we are checking the file type based on their extension and then performed operation accordingly. 

using System;
using System.Web.Mvc;
using System.IO;
using System.Drawing.Imaging;
using GenerateThumbnails.Conversion;

namespace GenerateThumbnails.Controllers
{
    public class HomeController : Controller
    {
        public HomeController() { }
        public ActionResult Index()
        {
            ViewBag.Title = "Home Page";

            return View();
        }


        [HttpPost]
        public ActionResult Index(string fileUrl)
        {
            //var path = "https://ol.baker.edu/webapps/dur-browserCheck-bb_bb60/samples/sample.xlsx?";
            //var path = "https://calibre-ebook.com/downloads/demos/demo.docx";

            if (!string.IsNullOrEmpty(fileUrl))
            {
                var tempPath = string.Empty;

                TypeConversion typeConv = new TypeConversion();
                if (Path.GetExtension(fileUrl).ToLower() == ".doc" || Path.GetExtension(fileUrl).ToLower() == ".docx" || Path.GetExtension(fileUrl).ToLower().Contains(".docx") || Path.GetExtension(fileUrl).ToLower().Contains(".doc"))
                {
                    typeConv.WordToPdf(fileUrl.ToString(), out tempPath);
                }
                else if (Path.GetExtension(fileUrl).ToLower() == ".xlsx" || Path.GetExtension(fileUrl).ToLower().Contains(".xlsx"))
                {
                    typeConv.ExcelToPdf(fileUrl.ToString(), out tempPath);
                }
                else if (Path.GetExtension(fileUrl).ToLower() == ".pdf" || Path.GetExtension(fileUrl).ToLower().Contains(".pdf"))
                {
                    typeConv.PdfURLToPdf(fileUrl.ToString(), out tempPath);
                }
                else
                {
                    return View();
                }

                Thumbnails thumbnail = new Thumbnails();
                var bitmapThumb = thumbnail.GetThumbnail(tempPath);

                if (!string.IsNullOrEmpty(tempPath))
                {
                    if (bitmapThumb != null)
                    {
                        thumbnail.SavethumbnailToImage(bitmapThumb, Path.GetPathRoot(Environment.SystemDirectory) + "WBTemp/" + DateTime.Now.Date.Day.ToString() + DateTime.Now.Date.Month.ToString()+ DateTime.Now.Date.Year+ DateTime.Now.Date.Hour+ DateTime.Now.Date.Minute+ DateTime.Now.Date.Second + ".jpef", "JPEG");
                    }
                    if (System.IO.File.Exists(tempPath))
                    {
                        System.IO.File.Delete(tempPath);
                    }
                }

                MemoryStream ms = new MemoryStream();
                bitmapThumb.Save(ms, ImageFormat.Jpeg);
                byte[] bmpBytes = ms.ToArray();
                string base64String = Convert.ToBase64String(bmpBytes);

                ViewBag.Image = base64String;
                return View();

            }
            return View();
        }

    }
}

 

On the client side [On View], we have created one form where we are passing the live URL of Docx, Xlsx or Pdf file and click to Submit button. On submit, it will perform the operation for generating the thumbnail image. Following is source code for View (Index.cshtml)

<div class="row">
  @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
  {

      <section id="contact">
        <div class="section-content">
          <h1 class="section-header">Generate <span class="content-header wow fadeIn " data-wow-delay="0.2s" data-wow-duration="2s"> Thumbnail</span></h1>
          <h3>Generate thumbnail using live url of docx, xlsx and pdf file</h3>
        </div>
        <div class="contact-section">
          <div class="container">
            <form>
              <div class="col-md-6 form-line">
                <div class="form-group">
                  <label for="exampleInputUsername">Enter File URL</label>
                  <input type="text" class="form-control" name="fileUrl" width="300" id="" placeholder="Enter URL Here">
                </div>               
                <div class="form-group" style="float:left;">                 
                  <button type="submit" class="btn btn-default submit"><i class="fa fa-paper-plane" aria-hidden="true"></i>  Generate Thumbnail</button>
                  <br />
                  
                </div>
              </div>
              <div class="col-md-6">
                <div class="form-group">
                  <label for="description"> Images</label>
                  <br />
                  <span>
                    # Default Thumbnail Width =150 and Height =180
                  </span>
                  <br />
                  @if (ViewBag.Image != null)
                  {
                      <img src="@String.Format("data:image/png;base64,{0}", ViewBag.Image)" />
                  }
                </div>
              </div>
            </form>
          </div>
        </div>
      </section>
  }

</div>

To show generated thumbnail live on View after generation, first we are converting image byte data to Base64String and pass it to View using ViewBag from Controller. On the View side, we are using <img> tag which take image data as base64 format and then show the image live.

@if (ViewBag.Image != null)
{
        <img src="@String.Format("data:image/png;base64,{0}", ViewBag.Image)" />
}

 

Here is the final output for this demonstration. Now I am going to pass following URL which is nothing but a Docx file HTTP URL and click to Generate Thumbnail button. Output will be produced as above image.

Thanks for reading this article, please share your valuable comments and feedbacks.