Click here to Skip to main content
15,868,016 members
Articles / Web Development / ASP.NET

Displaying the Contents of a PDF File in an ASP.NET Application using GhostScript

Rate me:
Please Sign up or sign in to vote.
4.33/5 (3 votes)
28 Jul 2012CPOL5 min read 59.6K   1.4K   18   6
A sample on displaying the contents of a PDF file in an ASP.NET application using GhostScript

After receiving quite a few requests on making the PDF image conversion work in a web application, I wanted to see how hard it would be to do. Not hard at all as it turns out, I had a nice working sample running with a bare 5 minutes of work.

The sample available for download below is a basic ASP.NET application, comprised of a single page with an IHttpHandler for displaying the image. In order to make this sample as easy as possible, it uses pure server side controls and code, nothing client side.

Getting Started

In order to run this sample, you'll need the Cyotek.GhostScript and Cyotek.GhostScript.PdfConversion.zip components described in a previous article.

You'll also need to download GhostScript. As with my other articles on the subject, please make sure you check their license terms - they seem very keen that people don't use the GPL version or distribute GhostScript without a commercial license.

Locating gsdll32.dll

In order for this to work, gsdll32.dll needs to be somewhere in your applications path. This could be in your system32 directory on 32bit Windows, or SysWOW64 on 64bit Windows.

While developing this sample, I also tried having the file in the bin directory of the website - this also worked fine. However, as the website was running on my local machine, it's probably running in Full Trust, and I have no idea if it will work in Medium Trust or lower.

I'm Running 64bit Windows!

Congratulations! I have nothing but issues with 32bit web servers. But I digress. The sample projects I have provided on this website all use the 32bit version of GhostScript. There is a 64bit version available, but I haven't downloaded it to test. Your options should be as follows:

  • Build against the 64 bit GhostScript DLL. This may need some refactoring if their public API has changed. At the very least, you'll need to change the DLL filename in the native method calls.
  • Using IIS7 or higher? Keep using the 32bit version, and set your worker pool to run in 32bit mode
  • Using IIS6? Commiserations, I feel your pain. The only option here, if you stay 32bit, is to have the entire IIS run as 32bit.

I have tested on a Windows 7 Professional 64bit machine as follows:

  • Firstly, using IIS Express which is running as a 32bit process
  • Secondly, using IIS7 with a custom application pool running in 32bit mode

Both of these scenarios worked perfectly well.

Creating the Solution

Create a new ASP.NET Web Forms Site

Note: Even though this example uses pure WebForms, there's no reason that this sort of code won't work fine in ASP.NET MVC or any other .NET framework of your choice.

Open up Default.aspx and add some controls similar to the following:

XML
<%@ Page Language="C#" AutoEventWireup="true" 
   CodeBehind="Default.aspx.cs" Inherits="GhostScriptWebTest._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>PDF Conversion Example</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <p>
            <asp:LinkButton runat="server" ID="previousLinkButton" 
               Text="Previous" OnClick="previousLinkButton_Click" />
            <asp:LinkButton runat="server" ID="nextLinkButton" 
               Text="Next" OnClick="nextLinkButton_Click" />
        </p>
        <p>
            <asp:Image runat="server" ID="pdfImage" 
               ImageUrl="~/PdfImage.ashx?fileName=sample.pdf&page=1" />
        </p>
    </div>
    </form>
</body>
</html>

The controls should be fairly self explanatory! The main thing of interest is the pdfImage Image control - this will call a Generic Handler that I'll describe in the next section. Note that VS2010 and VS2012 have another option, an ASP.NET Handler - this implements the same IHttpHandler interface but doesn't have a .ashx file and is registered differently. If you are using IIS7 or above, you're probably better off using that.

Note that by default the pdfImage control is pointing to a sample file named sample.pdf - add any old PDF to the root of your website and name it sample. Ensure that the Build Action for the PDF is set to Content, otherwise it won't be deployed with your application.

Creating the Image Handler

Tutorials on creating image handlers with IHttpHandler can be found scattered throughout the net, so I'll not go into how they work, but just describe the implementation I'm using in this example. Add a new generic handler to your project, then fill in the ProcessRequest method as follows. Make sure you add the two GhostScript API components to your solution and add references to them to your web application first!

C#
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;
using Cyotek.GhostScript.PdfConversion;

namespace GhostScriptWebTest
{
  public class PdfImage : IHttpHandler
  {
    public void ProcessRequest(HttpContext context)
    {
      string fileName;
      int pageNumber;
      Pdf2Image convertor;
      Bitmap image;

      fileName = context.Server.MapPath("~/" + 
      context.Request.QueryString["fileName"]);
      pageNumber = Convert.ToInt32(context.Request.QueryString["page"]);

      // convert the image
      convertor = new Pdf2Image(fileName);
      image = convertor.GetImage(pageNumber);

      // set the content type
      context.Response.ContentType = "image/png";

      // save the image directly to the response stream
      image.Save(context.Response.OutputStream, ImageFormat.Png);
    }

    public bool IsReusable
    { get { return true; } }
  }
}

Again, this is extremely simple code. I extract the query string of the request to obtain the file name of the PDF document to convert, and the page to display. I then create an instance of the Pdf2Image class, and grab an image of the specified page.

Next, you need to set the ContentType of the Response object so the web browser knows what to do with your content. Finally, I save the image directly to the response's OutputStream. Make sure that the format you save the image as matches the content type you've specified.

With these steps complete, building and running the website should present you with a pair of hyper links, and the first page of your PDF file as a static image. [Well, it will if you add a pair of blank event handlers for those defined for the two hyperlink buttons anyway.]

Simple Navigation

Now that we can display our PDF, we'll add some basic navigation. Open up the code behind file for Default.aspx and fill in the event handlers for the two hyperlink buttons.

C#
using System;
using System.Collections.Specialized;
using System.Web;
using Cyotek.GhostScript.PdfConversion;

namespace GhostScriptWebTest
{
  public partial class _Default : System.Web.UI.Page
  {
    protected void previousLinkButton_Click(object sender, EventArgs e)
    {
      this.IncrementPage(-1);
    }

    protected void nextLinkButton_Click(object sender, EventArgs e)
    {
      this.IncrementPage(1);
    }

    private void IncrementPage(int increment)
    {
      NameValueCollection queryString;
      int pageNumber;
      string pdfFileName;
      Pdf2Image converter;

      queryString = HttpUtility.ParseQueryString
      (pdfImage.ImageUrl.Substring(pdfImage.ImageUrl.IndexOf("?")));
      pdfFileName = queryString["fileName"];
      pageNumber = Convert.ToInt32(queryString["page"]) + increment;
      converter = new Pdf2Image(this.Server.MapPath("~/" + pdfFileName));

      if (pageNumber > 0 && pageNumber <= converter.PageCount)
        pdfImage.ImageUrl = string.Format
        ("~/PdfImage.ashx?fileName={0}&page={1}", pdfFileName, pageNumber);
    }
  }
}

As with the image handler, this code simply extracts the file name of the PDF file and the current page number. It also creates a new instance of the Pdf2Image class in order to obtain the number of pages in the document. If the new page number is in range, it updates the ImageUrl of the pdfImage causing the image handler to pull back the next page.

In Conclusion

This sample is pretty inefficient and at the very least should be caching the images. But, it's as simple an example as I can make. Hopefully, someone will find it useful. At the present time, I'm not working with the GhostScript API library so I suspect this will be the last article on the subject for the time being.

License

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


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionNot working in web application with multiple requests Pin
Member 20404593-Apr-18 22:19
Member 20404593-Apr-18 22:19 
QuestionDo you have a a complete working sample? Pin
veasnamuch26-Nov-14 21:58
veasnamuch26-Nov-14 21:58 
AnswerRe: Do you have a a complete working sample? Pin
Richard James Moss29-Nov-14 5:57
professionalRichard James Moss29-Nov-14 5:57 
GeneralRe: Do you have a a complete working sample? Pin
veasnamuch6-Dec-14 14:43
veasnamuch6-Dec-14 14:43 
QuestionDoes it cache images ? Pin
Harman Kumar20-Dec-13 2:23
Harman Kumar20-Dec-13 2:23 
AnswerRe: Does it cache images ? Pin
Richard James Moss20-Dec-13 5:50
professionalRichard James Moss20-Dec-13 5:50 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.