Generate Thumbnail From Live URL Of Microsoft Office And PDF file in ASP.NET MVC

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

Microsoft Office Documents

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

Getting thumbnails from images is not a very tough task; we can directly convert our image to Bitmap type and generate a thumbnail. So, it’s very simple and lots of articles are available there already on the Internet.

But getting thumbnails from live URLs (Docx, Xls, and PDF) is not tough but tricky. We have to make some extra effort to complete the thumbnail generation from these URLs.

For this demonstration, I am going to use ASP.NET MVC project and we are going to create the thumbnails from Microsoft Office Documents and PDF as well. These documents can be Microsoft Word document or Microsoft Excel worksheets or even PDF docs.

To create a new project, just follow the following instructions.

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

The project is ready for demonstration. To generate a thumbnail from the live URL, we will follow the given instructions.

  1. Download file in PDF format on temp location.
  2. Convert PDF file to a Bitmap image.
  3. Generate a thumbnail as Bitmap from the original Bitmap image.
  4. Save it to the preferred location.
  5. To show on View, convert it to Base64String and bind with the <img> tag.

Above, we have defined a couple of things which need to be completed to generate a thumbnail from the live URL and save it to any location or show it on the View.

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

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

Here, we are going to generate a thumbnail from three different types of file - 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 at the temporary location from the live URL.

  1. using System;  
  2. using Word = Microsoft.Office.Interop.Word;  
  3. using Excel = Microsoft.Office.Interop.Excel;  
  4. using System.IO;  
  5. using System.Net;  
  6.   
  7. namespace GenerateThumbnails.Conversion  
  8. {  
  9.     public class TypeConversion   
  10.     {  
  11.         private string _tempLocation = Path.GetPathRoot(Environment.SystemDirectory) + "WBTemp";  
  12.   
  13.         Word.Application wordApp = null;  
  14.         Word.Documents wdDocuments = null;  
  15.         Word.Document wdDocument = null;  
  16.   
  17.         Excel.Application excelApp = null;  
  18.         Excel.Workbooks xlBooks = null;  
  19.         Excel.Workbook xlBook = null;  
  20.   
  21.         public bool WordToPdf(string _sourcePath, out string _outputTempFilePath)  
  22.         {  
  23.             wordApp = new Word.Application();  
  24.             wdDocuments = wordApp.Documents;  
  25.   
  26.             try  
  27.             {  
  28.                 //Read word document file  
  29.                 wdDocument = wdDocuments.Open(_sourcePath);  
  30.   
  31.                 _outputTempFilePath = string.Empty;  
  32.   
  33.                 if (wdDocument != null)  
  34.                 {  
  35.                     _outputTempFilePath = GetTempTargetFilePath(_tempLocation);  
  36.   
  37.                     //Export word document file to pdf format  
  38.                     wdDocument.ExportAsFixedFormat(_outputTempFilePath, Word.WdExportFormat.wdExportFormatPDF);                    
  39.   
  40.                     return true;  
  41.                 }  
  42.             }  
  43.             catch (Exception ex)  
  44.             {  
  45.                 _outputTempFilePath = string.Empty;  
  46.   
  47.                 return false;  
  48.             }  
  49.             finally  
  50.             {  
  51.                 // Cleanup  
  52.                 GC.Collect();  
  53.                 GC.WaitForPendingFinalizers();  
  54.   
  55.                 wdDocument.Close(false);  
  56.                 NAR(wdDocument);  
  57.                 NAR(wdDocuments);  
  58.                 wordApp.Quit();  
  59.                 NAR(wordApp);  
  60.             }  
  61.   
  62.             return false;  
  63.         }  
  64.   
  65.         public bool ExcelToPdf(string _sourcePath, out string _outputTempFilePath)  
  66.         {  
  67.             excelApp = new Excel.Application();  
  68.   
  69.             try  
  70.             {  
  71.                 //Read word document file  
  72.                 xlBooks = excelApp.Workbooks;  
  73.                 xlBook = xlBooks.Open(_sourcePath);  
  74.   
  75.                 _outputTempFilePath = string.Empty;  
  76.   
  77.                 if (xlBook != null)  
  78.                 {  
  79.                     _outputTempFilePath = GetTempTargetFilePath(_tempLocation);  
  80.   
  81.                     //Export word document file to pdf format  
  82.                     xlBook.ExportAsFixedFormat(Excel.XlFixedFormatType.xlTypePDF, _outputTempFilePath);  
  83.   
  84.                     return true;  
  85.                 }  
  86.             }  
  87.             catch (Exception ex)  
  88.             {  
  89.                 _outputTempFilePath = string.Empty;  
  90.   
  91.                 return false;  
  92.             }  
  93.             finally  
  94.             {  
  95.                 // Cleanup  
  96.                 GC.Collect();  
  97.                 GC.WaitForPendingFinalizers();  
  98.   
  99.                 xlBook.Close(false);  
  100.                 NAR(xlBook);  
  101.                 NAR(xlBooks);  
  102.                 excelApp.Quit();  
  103.                 NAR(excelApp);                  
  104.             }  
  105.   
  106.             return false;  
  107.         }  
  108.   
  109.         public bool PdfURLToPdf(string _sourcePath, out string _outputTempFilePath)  
  110.         {  
  111.             using(var client = new WebClient())  
  112.             {  
  113.                 _outputTempFilePath = GetTempTargetFilePath(_tempLocation);  
  114.                 client.DownloadFile(_sourcePath, _outputTempFilePath);  
  115.                 return true;  
  116.             }  
  117.         }  
  118.   
  119.         private void NAR(object o)  
  120.         {  
  121.             try  
  122.             {  
  123.                 while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;  
  124.             }  
  125.             catch { }  
  126.             finally  
  127.             {  
  128.                 o = null;  
  129.             }  
  130.         }  
  131.   
  132.         public static string GetTempTargetFilePath(string _targetTempPath)  
  133.         {  
  134.             string _tempFilePath = string.Empty;  
  135.   
  136.             //Check temp directory exists or not  
  137.             if (!Directory.Exists(_targetTempPath))  
  138.             {  
  139.                 //Create new temp directory   
  140.                 Directory.CreateDirectory(_targetTempPath);  
  141.             }  
  142.   
  143.             var _fileName = "temp.pdf";  
  144.             _tempFilePath = _targetTempPath + "/" + _fileName;  
  145.   
  146.             if (File.Exists(_tempFilePath))  
  147.             {  
  148.                 File.Delete(_tempFilePath);  
  149.             }  
  150.             return _tempFilePath;  
  151.         }  
  152.     }  
  153. }  

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

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

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

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

  1. public static string GetTempTargetFilePath(string _targetTempPath)  
  2.         {  
  3.             string _tempFilePath = string.Empty;  
  4.   
  5.             //Check temp directory exists or not  
  6.             if (!Directory.Exists(_targetTempPath))  
  7.             {  
  8.                 //Create new temp directory   
  9.                 Directory.CreateDirectory(_targetTempPath);  
  10.             }  
  11.   
  12.             var _fileName = "temp.pdf";  
  13.             _tempFilePath = _targetTempPath + "/" + _fileName;  
  14.   
  15.             if (File.Exists(_tempFilePath))  
  16.             {  
  17.                 File.Delete(_tempFilePath);  
  18.             }  
  19.             return _tempFilePath;  
  20.         }  

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

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

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

NOTE

Be careful when using Microsoft.Office.Interop COM components because it generates memory overhead. So, leaving the method, be sure you have disposed of non-required COM component instances as we do in the "Finally" block.

We should release all the memory objects until all the referenced COM components disposed of, as follows. This is a best practice and it’s recommended by Microsoft.

  1. private void NAR(object o)  
  2.       {  
  3.           try  
  4.           {  
  5.               while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;  
  6.           }  
  7.           catch { }  
  8.           finally  
  9.           {  
  10.               o = null;  
  11.           }  
  12.       }  

NOTE

When using COM component, always follow the rule “don’t use double dots”.

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

NOTE

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

Above, we are done converting our live URLs of DOCX, XLSX, and PDF to a local file as PDF. Now, we can move to generate thumbnails from the temp PDF file.

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

In this method, first, we are generating an original Bitmap image from a temporary PDF file and then resize and compress it to export thumbnail based on the 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 returns an output as a Bitmap image. Following is the whole source code for the thumbnail class.

  1. using Microsoft.WindowsAPICodePack.Shell;  
  2. using System;  
  3. using System.IO;  
  4. using System.Drawing;  
  5.   
  6. namespace GenerateThumbnails.Conversion  
  7. {  
  8.     public class Thumbnails  
  9.     {         
  10.   
  11.         public Bitmap GetThumbnail(string _sourcePath)  
  12.         {  
  13.             const int bmpW = 150;  
  14.             const int bmpH = 180;  
  15.             Bitmap upBmp = null;  
  16.   
  17.             if (!string.IsNullOrEmpty(_sourcePath))  
  18.             {  
  19.                 if (Path.GetExtension(_sourcePath).ToLower() == ".pdf")  
  20.                 {  
  21.                     ShellFile shellFile = ShellFile.FromFilePath(_sourcePath);  
  22.                     upBmp = shellFile.Thumbnail.ExtraLargeBitmap;  
  23.                 }  
  24.             }  
  25.   
  26.             if (upBmp != null)  
  27.             {  
  28.                 Int32 newWidth = bmpW;  
  29.                 Int32 newHeight = bmpH;  
  30.   
  31.                 Bitmap newBmp = new Bitmap(newWidth, newHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);  
  32.   
  33.                 newBmp.SetResolution(72, 72);  
  34.                 Double upWidth = upBmp.Width;  
  35.                 Double upHeight = upBmp.Height;  
  36.   
  37.                 int newX = 0;  
  38.                 int newY = 0;  
  39.                 Double reDuce;  
  40.                 if (upWidth > upHeight)  
  41.                 {  
  42.                     reDuce = newWidth / upWidth;  
  43.                     newHeight = ((Int32)(upHeight * reDuce));  
  44.                     newY = ((Int32)((bmpH - newHeight) / 2));  
  45.                     newX = 0;  
  46.                 }  
  47.                 else if (upWidth < upHeight)  
  48.                 {  
  49.                     reDuce = newHeight / upHeight;  
  50.                     newWidth = ((Int32)(upWidth * reDuce));  
  51.                     newX = ((Int32)((bmpW - newWidth) / 2));  
  52.                     newY = 0;  
  53.                 }  
  54.                 else if (upWidth == upHeight)  
  55.                 {  
  56.                     reDuce = newHeight / upHeight;  
  57.                     newWidth = ((Int32)(upWidth * reDuce));  
  58.                     newX = ((Int32)((bmpW - newWidth) / 2));  
  59.                     newY = ((Int32)((bmpH - newHeight) / 2));  
  60.                 }  
  61.                 Graphics newGraphic = Graphics.FromImage(newBmp);  
  62.                 try  
  63.                 {  
  64.                     newGraphic.Clear(Color.White);  
  65.                     newGraphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;  
  66.                     newGraphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;  
  67.                     newGraphic.DrawImage(upBmp, newX, newY, newWidth, newHeight);  
  68.                     return newBmp;  
  69.                 }  
  70.                 catch (Exception ex)  
  71.                 {  
  72.                     string newError = ex.Message;  
  73.                     // lblError.Text = newError;  
  74.                 }  
  75.                 finally  
  76.                 {  
  77.                     upBmp.Dispose();  
  78.                    // newBmp.Dispose();  
  79.                     newGraphic.Dispose();  
  80.                 }  
  81.   
  82.                 
  83.             }  
  84.   
  85.             return upBmp;  
  86.         }  
  87.   
  88.         public void SavethumbnailToImage(Bitmap _bitmapImage, string _imagePath, string _typeOfImage)  
  89.         {  
  90.             if (_typeOfImage == "JPEG")  
  91.                 _bitmapImage.Save(_imagePath, System.Drawing.Imaging.ImageFormat.Jpeg);  
  92.             else  
  93.                 _bitmapImage.Save(_imagePath, System.Drawing.Imaging.ImageFormat.Png);  
  94.         }  
  95.     }  
  96. }  

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

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

  1. if (!string.IsNullOrEmpty(tempPath))  
  2.                 {  
  3.                     if (bitmapThumb != null)  
  4.                     {  
  5.                         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");  
  6.                     }  
  7.                     if (System.IO.File.Exists(tempPath))  
  8.                     {  
  9.                         System.IO.File.Delete(tempPath);  
  10.                     }  
  11.                 }  

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

  1. public void SavethumbnailToImage(Bitmap _bitmapImage, string _imagePath, string _typeOfImage)  
  2.         {  
  3.             if (_typeOfImage == "JPEG")  
  4.                 _bitmapImage.Save(_imagePath, System.Drawing.Imaging.ImageFormat.Jpeg);  
  5.             else  
  6.                 _bitmapImage.Save(_imagePath, System.Drawing.Imaging.ImageFormat.Png);  
  7.         }  

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

  1. MemoryStream ms = new MemoryStream();  
  2.                 bitmapThumb.Save(ms, ImageFormat.Jpeg);  
  3.                 byte[] bmpBytes = ms.ToArray();  
  4.                 string base64String = Convert.ToBase64String(bmpBytes);  
  5.   
  6.                 ViewBag.Image = base64String;  
  7.                 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.

  1. using System;  
  2. using System.Web.Mvc;  
  3. using System.IO;  
  4. using System.Drawing.Imaging;  
  5. using GenerateThumbnails.Conversion;  
  6.   
  7. namespace GenerateThumbnails.Controllers  
  8. {  
  9.     public class HomeController : Controller  
  10.     {  
  11.         public HomeController() { }  
  12.         public ActionResult Index()  
  13.         {  
  14.             ViewBag.Title = "Home Page";  
  15.   
  16.             return View();  
  17.         }  
  18.   
  19.   
  20.         [HttpPost]  
  21.         public ActionResult Index(string fileUrl)  
  22.         {  
  23.             //var path = "https://ol.baker.edu/webapps/dur-browserCheck-bb_bb60/samples/sample.xlsx?";  
  24.             //var path = "https://calibre-ebook.com/downloads/demos/demo.docx";  
  25.   
  26.             if (!string.IsNullOrEmpty(fileUrl))  
  27.             {  
  28.                 var tempPath = string.Empty;  
  29.   
  30.                 TypeConversion typeConv = new TypeConversion();  
  31.                 if (Path.GetExtension(fileUrl).ToLower() == ".doc" || Path.GetExtension(fileUrl).ToLower() == ".docx" || Path.GetExtension(fileUrl).ToLower().Contains(".docx") || Path.GetExtension(fileUrl).ToLower().Contains(".doc"))  
  32.                 {  
  33.                     typeConv.WordToPdf(fileUrl.ToString(), out tempPath);  
  34.                 }  
  35.                 else if (Path.GetExtension(fileUrl).ToLower() == ".xlsx" || Path.GetExtension(fileUrl).ToLower().Contains(".xlsx"))  
  36.                 {  
  37.                     typeConv.ExcelToPdf(fileUrl.ToString(), out tempPath);  
  38.                 }  
  39.                 else if (Path.GetExtension(fileUrl).ToLower() == ".pdf" || Path.GetExtension(fileUrl).ToLower().Contains(".pdf"))  
  40.                 {  
  41.                     typeConv.PdfURLToPdf(fileUrl.ToString(), out tempPath);  
  42.                 }  
  43.                 else  
  44.                 {  
  45.                     return View();  
  46.                 }  
  47.   
  48.                 Thumbnails thumbnail = new Thumbnails();  
  49.                 var bitmapThumb = thumbnail.GetThumbnail(tempPath);  
  50.   
  51.                 if (!string.IsNullOrEmpty(tempPath))  
  52.                 {  
  53.                     if (bitmapThumb != null)  
  54.                     {  
  55.                         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");  
  56.                     }  
  57.                     if (System.IO.File.Exists(tempPath))  
  58.                     {  
  59.                         System.IO.File.Delete(tempPath);  
  60.                     }  
  61.                 }  
  62.   
  63.                 MemoryStream ms = new MemoryStream();  
  64.                 bitmapThumb.Save(ms, ImageFormat.Jpeg);  
  65.                 byte[] bmpBytes = ms.ToArray();  
  66.                 string base64String = Convert.ToBase64String(bmpBytes);  
  67.   
  68.                 ViewBag.Image = base64String;  
  69.                 return View();  
  70.   
  71.             }  
  72.             return View();  
  73.         }  
  74.   
  75.     }  
  76. }  

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 "Submit" button. On submit, it will perform the operation for generating the thumbnail image. Following is the source code for View (Index.cshtml).

  1. <div class="row">  
  2.   @using (Html.BeginForm("Index""Home", FormMethod.Post, new { enctype = "multipart/form-data" }))  
  3.   {  
  4.   
  5.       <section id="contact">  
  6.         <div class="section-content">  
  7.           <h1 class="section-header">Generate <span class="content-header wow fadeIn " data-wow-delay="0.2s" data-wow-duration="2s"> Thumbnail</span></h1>  
  8.           <h3>Generate thumbnail using live url of docx, xlsx and pdf file</h3>  
  9.         </div>  
  10.         <div class="contact-section">  
  11.           <div class="container">  
  12.             <form>  
  13.               <div class="col-md-6 form-line">  
  14.                 <div class="form-group">  
  15.                   <label for="exampleInputUsername">Enter File URL</label>  
  16.                   <input type="text" class="form-control" name="fileUrl" width="300" id="" placeholder="Enter URL Here">  
  17.                 </div>                 
  18.                 <div class="form-group" style="float:left;">                   
  19.                   <button type="submit" class="btn btn-default submit"><i class="fa fa-paper-plane" aria-hidden="true"></i>  Generate Thumbnail</button>  
  20.                   <br />  
  21.                     
  22.                 </div>  
  23.               </div>  
  24.               <div class="col-md-6">  
  25.                 <div class="form-group">  
  26.                   <label for="description"> Images</label>  
  27.                   <br />  
  28.                   <span>  
  29.                     # Default Thumbnail Width =150 and Height =180  
  30.                   </span>  
  31.                   <br />  
  32.                   @if (ViewBag.Image != null)  
  33.                   {  
  34.                       <img src="@String.Format("data:image/png;base64,{0}", ViewBag.Image)" />  
  35.                   }  
  36.                 </div>  
  37.               </div>  
  38.             </form>  
  39.           </div>  
  40.         </div>  
  41.       </section>  
  42.   }  
  43.   
  44. </div>  

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

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

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

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