Monday, January 13, 2014

Creating PDF documents from webpage response using ABCpdf

ABCpdf is a handy third party (paid) tool to convert any form of documents to PDF files. It is also observed that in number of instances developers being asked to generate PDF files based upon a web page response. Here is the sample code to implement PDF generation from a target aspx file response.

In this example I am demonstrating how to effectively use ABCpdf in generating pdf files from an aspx page response; it could be any url that spits out html data. We can create GeneratePdf method in the asp.net web application and leverage HttpResponse Object to write out the pdf.

Let’s assume the url is http://loaduserdetails.aspx/id=1 and we our api once developed will allow us to call the code: GeneratePDF(“is http://loaduserdetails.aspx/id=1”);

public void GeneratePDF(string url)
{
  var pdfGenerator = new PdfGenerator();
  byte[] dataBytes = pdfGenerator .GetPdfDataBytes(pageUrl);
  Response.ContentType = "application/pdf";
   Response.AddHeader("content-disposition", "inline; filename=member_profile.pdf");
  Response.AddHeader("content-length", theData.Length.ToString());
  // ensure that the response is not cached. That would defeat the whole purpose
  Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
  Response.AddHeader("Cache-Control", " no-store, no-cache   issue fix
  Response.Cache.SetNoStore();
  Response.BinaryWrite(dataBytes);
  Response.End();
}
The PdfGenerator class will have dependency on ABCpdf and for illustration purposes I am using ABCpdf version8. The resulting PdfGenerator class code will look as below
    using WebSupergoo.ABCpdf8;
    public class PdfGenerator
    {
        private Doc _pdFdoc;
        public PdfGenerator()
        {
            this._pdFdoc = new Doc();
        }

       public byte[] GetPdfDataBytes(string aspxPageURL)
        { 
            //disable page caching
            _pdFdoc.HtmlOptions.PageCacheEnabled = false;
            _pdFdoc.HtmlOptions.UseNoCache = true;
            _pdFdoc.FontSize = 12;
            //load the document
            ifthis.LoadDocument(aspxPageURL))
            {
                // load the footer
                AddDocumentFooter();
            }

         var dataArray= _pdFdoc.GetData();
        _pdFdoc.Dispose(); 
        return dataArray;        
        }   
        private bool LoadDocument(string theUrl)
        {
            bool success=false;
            var pDdoc = new Doc();
            pDdoc.Rect.Inset(50, 50);
            try
            {
                var docPageCount = pDdoc.AddImageUrl(theUrl, true, 800, true);
                while (true)
                {
                    if (!pDdoc.Chainable(docPageCount))
                    {
                        break;
                    }
                    pDdoc.Page = pDdoc.AddPage();
                    docPageCount = pDdoc.AddImageToChain(docPageCount);
                }
                _pdFdoc.Append(pDdoc);
                success=true;
            }
            catch (Exception err)
            {
                //handle error
                _pdFdoc.AddHtml("<b>Unable to render page</b>");
            }
            finally
            {
                pDdoc.Dispose();
            }
            return success;
        } 

  private void AddDocumentFooter()
        {
            _pdFdoc.Rect.String = "30 790 600 30";
            _pdFdoc.Rect.Position(0, 30);
            _pdFdoc.HPos = 1.0; // Align text right
            _pdFdoc.FontSize = 10;
            for (var i = 1; i <= _pdFdoc.PageCount; i++)
            {
                _pdFdoc.Page = i;
                _pdFdoc.PageNumber = i;
                _pdFdoc.Font = _pdFdoc.EmbedFont("Tahoma");                
                _pdFdoc.AddText("Document Generated by MyApplication  Page " 
                                                                    + i + " of " + _pdFdoc.PageCount);                
                _pdFdoc.Flatten();
            }

        }

    }

2 comments: