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

ASP.NET PDF Viewer User Control Without Acrobat Reader Installed on Client or Server

By , 9 Sep 2012
 
PDFViewASP

Introduction

This article discusses how to create an ASP.NET PDF Viewer User Control that is not dependent on Acrobat software being installed.

Fundamental Concepts

  1. Get a page count of the PDF document that needs to be viewed to define your page number boundaries (PdfLibNet - XPDF) 
  2. Convert the PDF document (specific page on demand) to a raster image format (PdfLibNet - XPDF)  
  3. Convert the current page to be viewed into a PNG file
  4. Display the PNG file in an image on a web page 

Several utility classes were created or added from others which expose functionality needed from the various helper libraries.

  1. AFPDFLibUtil.vb (contains methods to create Bookmark HTML, Search, get page count, convert PDF to PNG)
  2. ImageUtil.vb (contains methods for image manipulation such as resize, rotation, conversion, etc.)
  3. ASPPDFLib.vb (contains generic wrapper functions that call specific technologies)
  4. PDFViewer.ascx.vb (contains code behind for the PDF Viewer User Control)
  5. PDFViewer.ascx (contains client side HTML/JavaScript for the PDF Viewer User Control)

Using the Code 

ASP Server Configuration Requirements

  • You must give the ASPNET user (IISUSR or ASPNET or Network services user) permission to modify (read/write) the /PDF and /render directories.
  • You must give the ASPNET user (IISUSR or ASPNET or Network services user) permission to  Read & Execute the /bin diirectory.
  • The DLL PDFLibNet.dll must be available to the page. You might have to register it with the GAC depending on your operating system to make it available to the application.
  • PDFLibNet.dll and PDFLibCmdLine.exe must both be compiled with the same architecture (x86 or x64) 
  • If x86 is used, you must set the advanced settings of the AppPool to allow execution of 32-bit applications if you are on a 64-bit OS.  

This project consists of 3 DLLs that must all be in the same directory:

  • PDFLibNET.dll
  • StatefullScrollPanel.dll
  • PDFViewASP.dll

To place a PDF Viewer User Control on a web page:   

<uc1:PDFViewer ID="PDFViewer1" runat="server" /> 

Set the FileName property to view the PDF file in the code behind:

      Dim pdfFileName As String = Request.MapPath("PDF") & "\" & "myPDF.pdf"
      If ImageUtil.IsPDF(pdfFileName) Then
        ErrorLabel.Visible = False
        PDFViewer1.FileName = pdfFileName
      Else
        ErrorLabel.Text = "Only PDF files (*.pdf) are allowed to be viewed."
        ErrorLabel.Visible = True
      End If

The essential part of this solution is extracting the current page to be viewed from a PDF file. Since we are using ASP.NET, I chose to implement a file based solution to avoid memory management issues when trying to persist PDF byte streams for multiple clients. I chose to extract a page from PDF using PDFLibNet and store it to the File System as a PNG image. I chose PNG since it uses ZIP compression which results in a lossless compressed image and small file size.

    'Modified for ASP usage
    Public Shared Function GetPageFromPDF(ByVal filename As String, _
	ByVal destPath As String, ByRef PageNumber As Integer, _
	Optional ByVal DPI As Integer = RENDER_DPI, _
	Optional ByVal Password As String = "", _
	Optional ByVal searchText As String = "", _
	Optional ByVal searchDir As SearchDirection = 0) As String
    GetPageFromPDF = ""
    Dim pdfDoc As New PDFLibNet.PDFWrapper
    pdfDoc.RenderDPI = 72
    pdfDoc.LoadPDF(filename)
    If Not Nothing Is pdfDoc Then
      pdfDoc.CurrentPage = PageNumber
      pdfDoc.SearchCaseSensitive = False
      Dim searchResults As New List(Of PDFLibNet.PDFSearchResult)
      If searchText <> "" Then
        Dim lFound As Integer = 0
        If searchDir = SearchDirection.FromBeginning Then
          lFound = pdfDoc.FindFirst(searchText, _
          	PDFLibNet.PDFSearchOrder.PDFSearchFromdBegin, False, False)
        ElseIf searchDir = SearchDirection.Forwards Then
          lFound = pdfDoc.FindFirst(searchText, _
          	PDFLibNet.PDFSearchOrder.PDFSearchFromCurrent, False, False)
        ElseIf searchDir = SearchDirection.Backwards Then
          lFound = pdfDoc.FindFirst(searchText, _
          	PDFLibNet.PDFSearchOrder.PDFSearchFromCurrent, True, False)
        End If
        If lFound > 0 Then
          If searchDir = SearchDirection.FromBeginning Then
            PageNumber = pdfDoc.SearchResults(0).Page
            searchResults = GetAllSearchResults(filename, searchText, PageNumber)
          ElseIf searchDir = SearchDirection.Forwards Then
            If pdfDoc.SearchResults(0).Page > PageNumber Then
              PageNumber = pdfDoc.SearchResults(0).Page
              searchResults = GetAllSearchResults(filename, searchText, PageNumber)
            Else
              searchResults = SearchForNextText(filename, searchText, _
						PageNumber, searchDir)
              If searchResults.Count > 0 Then
                PageNumber = searchResults(0).Page
              End If
            End If
          ElseIf searchDir = SearchDirection.Backwards Then
            If pdfDoc.SearchResults(0).Page < PageNumber Then
              PageNumber = pdfDoc.SearchResults(0).Page
              searchResults = GetAllSearchResults(filename, searchText, PageNumber)
            Else
              searchResults = SearchForNextText(filename, searchText, _
						PageNumber, searchDir)
              If searchResults.Count > 0 Then
                PageNumber = searchResults(0).Page
              End If
            End If
          End If
        End If
      End If
      Dim outGuid As Guid = Guid.NewGuid()
      Dim output As String = destPath & "\" & outGuid.ToString & ".png"
      Dim pdfPage As PDFLibNet.PDFPage = pdfDoc.Pages(PageNumber)
      Dim bmp As Bitmap = pdfPage.GetBitmap(DPI, True)
      bmp.Save(output, System.Drawing.Imaging.ImageFormat.Png)
      bmp.Dispose()
      GetPageFromPDF = output
      If searchResults.Count > 0 Then
        GetPageFromPDF = HighlightSearchCriteria(output, DPI, searchResults)
      End If
      pdfDoc.Dispose()
    End If
  End Function

In the PDFViewer code, a page number is specified and:

  • The page is loaded from the PDF file and converted to a PNG file.
  • We add the PNG file name to the ASP.NET Cache with an expiration of 5 minutes to ensure that we don't leave rendered images lying around on the server.
  • The ImageUrl is updated with the path to the PNG file.

PDFViewer.ascx.vb

 Private Sub DisplayCurrentPage(Optional ByVal doSearch As Boolean = False)
   'Set how long to wait before deleting the generated PNG file
   Dim expirationDate As DateTime = Now.AddMinutes(5)
   Dim noSlide As TimeSpan = System.Web.Caching.Cache.NoSlidingExpiration
   Dim callBack As New CacheItemRemovedCallback(AddressOf OnCacheRemove)
   ResizePanels()
   CheckPageBounds()
   UpdatePageLabel()
   InitBookmarks()
   Dim destPath As String = Request.MapPath("render")
   Dim indexNum As Integer = (parameterHash("CurrentPageNumber") - 1)
   Dim numRotation As Integer = parameterHash("RotationPage")(indexNum)
   Dim imageLocation As String
   If doSearch = False Then_
     imageLocation = ASPPDFLib.GetPageFromPDF(parameterHash("PDFFileName"), _
     destPath, parameterHash("CurrentPageNumber"), parameterHash("DPI"), _
     parameterHash("Password"), numRotation)
   Else
     imageLocation = ASPPDFLib.GetPageFromPDF(parameterHash("PDFFileName"), destPath _
                                              , parameterHash("CurrentPageNumber") _
                                              , parameterHash("DPI") _
                                              , parameterHash("Password") _
                                              , numRotation, parameterHash("SearchText") _
                                              , parameterHash("SearchDirection") _
                                              )
     UpdatePageLabel()
   End If
   ImageUtil.DeleteFile(parameterHash("CurrentImageFileName"))
   parameterHash("CurrentImageFileName") = imageLocation
   'Add full filename to the Cache with an expiration
   'When the expiration occurs, it will call OnCacheRemove which will delete the file
   Cache.Insert(New Guid().ToString & "_DeleteFile", imageLocation, _
   	Nothing, expirationDate, noSlide, _
   	System.Web.Caching.CacheItemPriority.Default, callBack)
   Dim matchString As String = _
	Request.MapPath("").Replace("\", "\\") ' escape backslashes
   CurrentPageImage.ImageUrl = Regex.Replace(imageLocation, matchString & "\\", "~/")
 End Sub

 Private Sub OnCacheRemove(ByVal key As String, ByVal val As Object, _
  	ByVal reason As CacheItemRemovedReason)
   If Regex.IsMatch(key, "DeleteFile") Then
     ImageUtil.DeleteFile(val)
   End If
 End Sub

ASPPDFLib.vb

    Public Shared Function GetPageFromPDF(ByVal sourceFileName As String _
                                        , ByVal destFolderPath As String _
                                        , ByRef iPageNumber As Integer _
                                        , Optional ByVal DPI As Integer = 0 _
                                        , Optional ByVal password As String = "" _
                                        , Optional ByVal rotations As Integer = 0 _
                                        , Optional ByVal searchText As String = "" _
                                        , Optional ByVal searchDir As Integer = _
                                        	AFPDFLibUtil.SearchDirection.FromBeginning _
                                        ) As String
    GetPageFromPDF = AFPDFLibUtil.GetPageFromPDF(sourceFileName, _
	destFolderPath, iPageNumber, DPI, password, searchText, searchDir)
    ImageUtil.ApplyRotation(GetPageFromPDF, rotations)
  End Function

Points of Interest

This project was made possible due to various open source libraries that others were kind enough to distribute freely. I would like to thank the PDFLibNet developer Antonio Sandoval and Foo Labs (XPDF) for their efforts.

History

  • 1.0 - Initial version
  • 1.1 - Added Search capabilities, reduced DLL dependencies, made PDF subsystem use XPDF only
  • 1.2 - Replaced PDFLibNet.dll to fix incorrect configuration error 0x800736B1
  • 1.3 - Optimized search routines
  • 1.4 - Remove outdated links to legacy content
  • 1.5 - Updated permissions information

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

Ron Schuler
Software Developer
United States United States
Member
No Biography provided

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   
QuestionCan We Print this PDF Document with print dialog box PinmemberPraveenGajawada21 Apr '13 - 21:23 
Hi Ron,thanks for this example
 
Hoe can i print this pdf document programmatically.means with this example we can show pdf document as images.but i want to give a print option to print this pdf document.i want to open a print dialog box.
i tried to print programmatically but in my app when i click on print button it starts printing pdf.but iwant to open a print dialog box and select printer setings like page size and all..can you help me out..
QuestionArabic Fonts Pinmembermon8127 Jan '13 - 19:32 
Empty string while Getbitmap in case PDF having arabic text
How to resolve please
UAE
Abu Dhabi
Smart Systems
Software Developer

QuestionCan you help me to create pdf editor PinmemberSMayur19 Jan '13 - 2:40 
Hello, your code helped me a lot to create pdf reader and I am succeed in creating pdf reader, but now I want to create pdf editor like say right now it's providing facility to user to view any pdf but I want to give them facility of editing it. So can you help me in this?
AnswerRe: Can you help me to create pdf editor Pinmvpadriancs17hrs 11mins ago 
QuestionC# code for this Pinmemberaravindnass1 Dec '12 - 18:24 
haiii... Ron Schuler ...thanks for your article ..Its nice..actually I am looking for this..,but I am Developing with c#. It will be great full if you give me Code in C# language.
Questionhow to download the code for this article Pinmembervinaykd198121 Nov '12 - 1:08 
how to download the code for this article ? there is no any download link.
AnswerRe: how to download the code for this article Pinmemberzmmkele29 Nov '12 - 16:17 
Questionprotected pdf Not working.... PinmemberGaurav12214 Nov '12 - 2:27 
protected pdf control shows a blank page.
AnswerRe: protected pdf Not working.... PinmemberDadajiIn30 Nov '12 - 18:37 
QuestionHow to integrate this code in Asp.Net MVC ? PinmemberSachin Panchal30 Oct '12 - 23:55 
Hi Ron,
 
How can I integrate this control in Asp.net MVC?
Regards,
Sachin

GeneralMy vote of 5 PinmemberSavalia Manoj M29 Oct '12 - 1:39 
Good
Questionprotected pdf problem Pingroupivanruisoto23 Sep '12 - 23:36 
Hi,
 
When i try show a protected pdf the control shows a blank page.
but it detects correctly the number of pages. I have downloaded the proyect and i have converted it in Framework4.0. I am working in 32bit.
QuestionForm Fields PinmemberMike Stiles14 Sep '12 - 11:53 
What are your plans for the ability to set or get PDF Form Fields and insert png images (pictures of actual signatures as captured by a Topaz Signature Pad, and stored in SQL as image)?
GeneralMy vote of 5 PinmemberAnurag Gandhi11 Sep '12 - 3:16 
Good One!!
QuestionC# version of PDF viewer Pinmemberk.sathishkumar10 Sep '12 - 22:18 
Hi Ron,
 
I have tried to convert your code into C# by using the varies conversion tools but still couldn't get the error free code.
 
so it would be really helpful for lot people here if you post the c# version of above code.
 
Thanks in advance.
 
Regards,
Sathish
GeneralMy vote of 5 PinmemberFarhan Ghumra10 Sep '12 - 19:30 
Excellent
QuestionNot working with Online Server Database Pinmembersanju ahuja9 Sep '12 - 7:48 
.This is not working with server database files
QuestionPDF Viewer not working when impersonate = true Pinmemberpandiarajan198610 Aug '12 - 0:10 
Hi,
 
im using this PDF Viewer, its not working when Identity impersonate = "true" in Web config. is there any solution
Questionpdf viewer Pinmemberslamet supriyadi2 Aug '12 - 20:18 
any example for C# ?
QuestionAttempted to read or write protected memory. This is often an indication that other memory is corrupt. Pinmemberrabbwhite24 Jul '12 - 22:52 
Dim output As String = Server.MapPath("render/") & outGuid.ToString & ".png"
Dim pdfPage As PDFLibNet.PDFPage = pdfDoc.Pages(pdfDoc.CurrentPage)
Dim bmp As Bitmap = pdfPage.GetBitmap(72, False) ' had error on this line *****
bmp.Save(output, System.Drawing.Imaging.ImageFormat.Png)
bmp.Dispose()
 
Exception Details: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
 
Please advice
 
Thank you very much
Questionpassword problem PinmemberDonCreAtive20 Jul '12 - 3:46 
i'm having problems displaying any pdf file.at all the files i tried to opemn the inccrrect pasword appeared. problem is that the pdf's haven't got any password.., i copied the x64 files as you said in a previous post but still the password problem.., if you cand help me.., thanks very much
AnswerRe: password problem Pinmemberkumargtl8 Aug '12 - 1:36 
GeneralRe: password problem PinmemberMohammedHabeeb8 Sep '12 - 21:31 
GeneralRe: password problem PinmemberRon Schuler9 Sep '12 - 4:27 
QuestionAgian , help me : System.Runtime.InteropServices.ExternalException Pinmemberreza_project12 Jun '12 - 18:34 
Hi
when i set file name of control and run project
the control appears but that does not show the page of the PDF file
and when i check the url of the picture that must show in control i find this error:
i mean the picture does not load !!!
 

exception=System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.%0d%0a   at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)%0d%0a   at System.Drawing.Image.Save(String filename, ImageFormat format)%0d%0a   at PDFLibCmdLine.PDFLibHelper.GetPageFromPDF(String filename, String destPath, Int32& PageNumber, Size objSize, Int32 DPI, String Password, String searchText, SearchDirection searchDir, Int32 useMuPDF)%0d%0a   at PDFLibCmdLine.Module1.Main()
 
please check it and say the solution of it!
QuestionAccess is denied, please help! Pinmemberbehzad200024 Apr '12 - 9:51 
Hi,
After set full control of IIS permissions, get error:
System.ComponentModel.Win32Exception: Access is denied
Stack:
[Win32Exception (0x80004005): Access is denied]
   System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo) +1806
   System.Diagnostics.Process.Start() +69
   PDFViewASP.CmdHelper.ExecuteCMD(String cmd, String args) +140
   PDFViewASP.ExternalPDFLib.GetPDFPageCount(String appPath, String filepath, String userPassword) +84
   PDFViewASP.WebUserControl1.InitPageRange() +126
   PDFViewASP.WebUserControl1.InitialFileLoad(String value) +126
   PDFViewASP.WebUserControl1.set_FileName(String value) +91
   viewer.Page_Load(Object sender, EventArgs e) +192
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +99
   System.Web.UI.Control.LoadRecursive() +50
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627
B.E.H.Z.A.D

AnswerRe: Access is denied, please help! Pinmemberbehzad20008 May '12 - 0:51 
QuestionLicensing? Pinmembersdas00715 Mar '12 - 3:18 
This is one of the best implementation I have seen. I want to use it as it is for my company intranet site.
 
Do we need to buy licenses for any underlying DLLs???
AnswerRe: Licensing? PinmemberRon Schuler15 Mar '12 - 14:54 
AnswerRe: Licensing? Pinmemberkumargtl8 Aug '12 - 3:02 
GeneralRe: Licensing? PinmemberRon Schuler8 Aug '12 - 3:07 
QuestionClinet side PDF rendering in HTML5 Pinmembercodeivan9 Mar '12 - 12:49 
I was considering this approach however didn't like the idea high burden it puts on the server for rendering and slow performance. Besides xpdf is not a robust and was crashing etc.
 
We ended up with PDFTron PDFNet WebViewer:
 
http://www.pdftron.com/pdfnet/webviewer/demo.html
AnswerRe: Clinet side PDF rendering in HTML5 PinmemberRon Schuler9 Mar '12 - 15:04 
QuestionASP.NET PDF Viewer User Control Without Acrobat Reader Installed on Client or Server Pinmembermunish199016 Feb '12 - 23:28 
Hey ,
I am working on PDF Viewer User Control without Acrobat Reader Installed on Client or Server and i got the code from following link:
'<a href="http://www.codeproject.com/Articles/41933/ASP-NET-PDF-Viewer-User-Control-Without-Acrobat-Re">ASP.NET PDF Viewer User Control Without Acrobat Reader Installed on Client or Server</a>[<a href="http://www.codeproject.com/Articles/41933/ASP-NET-PDF-Viewer-User-Control-Without-Acrobat-Re" target="_blank" title="New Window">^</a>]'
But i want this code in C#. Please provide me this code in C#.
 
Regards,
Munish
AnswerRe: ASP.NET PDF Viewer User Control Without Acrobat Reader Installed on Client or Server PinmemberVibs18 Jun '12 - 0:52 
QuestionWin32Exception (0x80004005): The system cannot find the path specified PinmemberRodrigo Galvao28 Dec '11 - 2:35 
Hi, to test I placed the files under \pdfviewer\ and I'm receiving an error Win32Exception (0x80004005): The system cannot find the path specified. Somebody know how do I fix it?
 
Thanks,
 
Great article!
 
Rod
AnswerRe: Win32Exception (0x80004005): The system cannot find the path specified Pinmemberbehzad20008 May '12 - 0:48 
QuestionUnicode Bookmark Pinmemberreza_project27 Dec '11 - 19:56 
Hi
I'm using this control and it's very useful
tanks a lot
but i get a problem with Persian Bookmark!!!
when i choose a PDF with Persian bookmark it does not show correct text
for example these values:
 
    ¬ëں«ëںêى ?¢ں
    هى©«¢
    ھë§?ï ëںêى ™ë¢يë ?¦يه
    êن©يç
    ¢ىïى ?ëë§ى ھï© ?ںëں?ى
    ?ى ¢¦­
 
I'm glad to help me
QuestionYou Rock!!! PinmemberMember 83893565 Dec '11 - 15:36 
Thanks,
 
This gets me headed in the right direction. My requirements are simple.
1. Render SOP & Specification archives online (currently in PDF).
2. Disable "right click" Downloading,
3. Allow Selective Printing privs (based on UserName & Password).
 
Had a difficult time finding a way to prevent users from doing both with Acrobat Reader plugin.
 

 
Thanks
 
Shane Big Grin | :-D
QuestionHelp me Pinmemberreza_project29 Nov '11 - 0:36 
Hi buddy
when im running this project i get this error with bellow line code:
 
Quote:
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index<</blockquote>
 
 Dim numRotation As Integer = parameterHash("RotationPage")(indexNum)
 
this line is coded in PDFViewver.ascs.vb in line 286
 
can any one explain why i get this err??
tanks in advanced
with respect
AnswerRe: Help me PinmemberRon Schuler29 Nov '11 - 6:49 
QuestionTHE SAME WORKING IN LOCAL BUT NOT IN SERVER PinmemberMember 774197425 Oct '11 - 2:41 
Dear All,
the above code worked me for local asp.net development server,but when i host in our company's iis server it is not working ,if anyone knows pls help me.
Bugcan not work under iis 7.5 server2008 r2 64bit Pinmemberranzige14 Oct '11 - 22:55 
bin&render directory allow IIS User to read & execute
Website run as an application in IIS.
And updated the x64 dll&exe file from google code.
 
i can see the index of the treeview,but no pics on the right side.
i checked the render directory found no png pics .
 
PLZ Help me
GeneralRe: can not work under iis 7.5 server2008 r2 64bit PinmemberRon Schuler9 Sep '12 - 4:24 
QuestionNew version in SVN repository PinmemberRon Schuler11 Aug '11 - 3:14 
Get the latest from the Google SVN repository.
I have removed all of the redundant process calls and the performance is significantly better.
AnswerRe: New version in SVN repository PinmemberSai_U27 Oct '11 - 18:40 
QuestionUpdate progress ... PinmemberRon Schuler7 Aug '11 - 13:59 
As I'm debugging the code, I notice a lot of redundant calls to the external PDF process.
I'll finish it this week.
I'm going to optimize it into:
One initial call per file name that gets bookmarks, page count, and password requirements
One call that calculates the optimal DPI and gets the page graphic.
 
This will result in only one call per page navigation (5 are being done now).
 
I apologize for the inefficiencies (I should have done more debug testing).
 
I will update the repository and the ZIP file attached to the article in the next few days.
Generalpdf 400mb not opening PinmemberGuru Prasath N7 Aug '11 - 8:55 
i am have the issue that user control does not opening large 400mb pdf files,error comes as bad request.Any solution please.I am changed time out high, maxRequestLength higher.
GeneralRe: pdf 400mb not opening PinmemberRon Schuler7 Aug '11 - 14:01 
GeneralRe: pdf 400mb not opening Pinmemberraveeshdadheech11 Nov '11 - 21:42 

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 9 Sep 2012
Article Copyright 2009 by Ron Schuler
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid