Search code examples
c#asp.netmemory-leaksapplication-poolabcpdf

Center Website On One Page with ABCPDF


I have code that does a good job of centering html inside one page on abcpdf. This was provided to me from websupergoo company that created abcpdf. However, my application pool keeps shutting down, and I believe its a performance issue. I even have caching enabled. Is there anyway to optimize this code. Basically what is happening is the code makes calls to a html page, and figures out the boundary dimensions to set the browser width so it can fit within the pdf dimensions. Doing this makes calls over and over to a html page, but I was told if its cached it wouldn't make an actual request but read the cache. There just has to be a easier way to do this since it does take a while to render. This issue seems to happen when multiple requests to a url that uses abcpdf at once.

            using (var doc = new Doc())
            {
                doc.HtmlOptions.Timeout = 60000;
                doc.HtmlOptions.PageCacheEnabled = true;
                doc.HtmlOptions.PageCacheExpiry = 600000;

                doc.HtmlOptions.Engine = Engine;
                doc.Rect.Inset(PageInsetHorizontal, PageInsetVertical);
                doc.Color.String = "255, 255, 255";

                const double heightTolerance = 18; // in points, the max allowed space at the bottom
                const int widthIncrement = 96; // in pixels, just an appropriate initial browser width increment
                var tallWidth = 0; // the lower browser width
                var wideWidth = 0; // the upper browser width
                Debug.WriteLine("Adding Url: " + Url);
                var id = doc.AddImageUrl(Url);
                var scrollWidth = doc.GetInfoInt(id, "ScrollWidth");
                var contentWidth = doc.GetInfoInt(id, "ContentWidth");
                var toContentWidth = contentWidth - scrollWidth;

                while (true)
                {
                    var width = doc.GetInfoInt(id, "ContentWidth");
                    var height = doc.GetInfoInt(id, "ContentHeight");

                    Debug.WriteLine("Initial Content Width: " + width);
                    Debug.WriteLine("Initial Content Height: " + height);

                    var tooTall = false;
                    var docScrollWidth = doc.GetInfoInt(id, "ScrollWidth");

                    Debug.WriteLine("Scroll Width: " + docScrollWidth);

                    if (docScrollWidth < scrollWidth)
                    {
                        scrollWidth = docScrollWidth;
                        contentWidth = scrollWidth + toContentWidth;

                        Debug.WriteLine("New Scroll Width: " + scrollWidth);
                        Debug.WriteLine("New Content Width: " + contentWidth);
                    }

                    Debug.WriteLine("Width: " + width);

                    if (width + 1 < contentWidth)
                    {
                        Debug.WriteLine("Too Tall: " + Url);
                        tooTall = true;
                    }
                    // assuming doc.Rect originally specifies the maximum bounding area
                    if (tooTall || doc.Rect.Width * height > doc.Rect.Height * width)
                    {
                        Debug.WriteLine("TOO TALL");
                        Debug.WriteLine("Delete Html: " + id);

                        // too tall
                        doc.Delete(id);

                        Debug.WriteLine("Browser Width: " + doc.HtmlOptions.BrowserWidth);

                        if (doc.HtmlOptions.BrowserWidth == 0)
                        {
                            doc.HtmlOptions.BrowserWidth = Convert.ToInt32(height*doc.Rect.Width/doc.Rect.Height);
                            Debug.WriteLine("New BrowserWidth: " + doc.HtmlOptions.BrowserWidth);
                        }
                        else
                        {
                            tallWidth = doc.HtmlOptions.BrowserWidth;

                            Debug.WriteLine("Tall Width: " + tallWidth);
                            Debug.WriteLine("Wide Width: " + wideWidth);

                            if (wideWidth == 0)
                            {
                                doc.HtmlOptions.BrowserWidth = tallWidth + widthIncrement;
                                Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
                            }
                            else if (tallWidth + 1 < wideWidth)
                            {
                                doc.HtmlOptions.BrowserWidth = (tallWidth + wideWidth)/2;
                                Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
                            }
                            else
                            {
                                doc.HtmlOptions.BrowserWidth = wideWidth;
                                Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
                                Debug.WriteLine("Adding Url: " + Url);
                                Debug.WriteLine("Found Fit");
                                doc.AddImageUrl(Url);
                                break;
                            }
                        }
                    }
                    else if (doc.Rect.Width * height < (doc.Rect.Height - heightTolerance) * width)
                    {
                        Debug.WriteLine("TOO WIDE");
                        Debug.WriteLine("Browser Width: " + doc.HtmlOptions.BrowserWidth);

                        // too wide
                        if (doc.HtmlOptions.BrowserWidth == 0)
                        {
                            doc.HtmlOptions.BrowserWidth = Convert.ToInt32(height * doc.Rect.Width / doc.Rect.Height);
                            Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
                        }
                        else
                        {
                            wideWidth = doc.HtmlOptions.BrowserWidth;

                            Debug.WriteLine("Tall Width: " + tallWidth);
                            Debug.WriteLine("Wide Width: " + wideWidth);

                            if (tallWidth == 0)
                            {
                                doc.HtmlOptions.BrowserWidth = wideWidth >= 2 * widthIncrement ? wideWidth - widthIncrement : wideWidth / 2;
                                Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
                            }
                            else if (tallWidth + 1 < wideWidth)
                            {
                                doc.HtmlOptions.BrowserWidth = (tallWidth + wideWidth)/2;
                                Debug.WriteLine("New Browser Width: " + doc.HtmlOptions.BrowserWidth);
                            }
                            else
                            {
                                Debug.WriteLine("Found Fit");

                                break;
                            }
                        }

                        Debug.WriteLine("Delete Html: " + id);

                        doc.Delete(id);
                    }
                    else
                        break;

                    Debug.WriteLine("Adding Url: " + Url);

                    id = doc.AddImageUrl(Url);
                }

                using (var ms = new MemoryStream())
                {
                    doc.Save(ms);
                    if (ms.CanSeek)
                    {
                        ms.Seek(0, SeekOrigin.Begin);
                    }
                    return ms.GetBuffer();
                }
            }

Solution

  • I found some other code and I tweaked it and this seems to work great.

    using (var doc = new Doc())
    {
      if(!EnableCache)
        doc.HtmlOptions.PageCacheClear();
    
        if (MakeLandscape)
        {
          var w = doc.MediaBox.Width;
          var h = doc.MediaBox.Height;
          var l = doc.MediaBox.Left;
          var b = doc.MediaBox.Bottom;
    
          doc.Transform.Rotate(90, l, b);
          doc.Transform.Translate(w, 0);
    
          doc.Rect.Width = h;
          doc.Rect.Height = w;
        }
    
        doc.HtmlOptions.Timeout = 60000;
        doc.HtmlOptions.PageCacheEnabled = EnableCache;
        doc.HtmlOptions.PageCacheExpiry = 600000;
    
        doc.HtmlOptions.Engine = Engine;
        doc.Rect.Inset(PageInsetHorizontal, PageInsetVertical);
        doc.Color.String = "255, 255, 255";
    
        doc.HtmlOptions.Paged = false;
        doc.HtmlOptions.BrowserWidth = (MakeLandscape ? PageWidth + PageInsetHorizontal : PageHeight + PageInsetVertical) * Convert.ToInt32(doc.Rect.Width / doc.Rect.Height);
    
        var id = doc.AddImageUrl(Url);
    
        if (MakeLandscape)
        {
          var scrollWidth = doc.GetInfoInt(id, "ScrollWidth");
          var contentWidth = doc.GetInfoInt(id, "ContentWidth");
    
          if (scrollWidth > contentWidth)
          {
            var scrollHeight = doc.GetInfoInt(id, "ScrollHeight");
            doc.Delete(id);
            doc.HtmlOptions.BrowserWidth = Convert.ToInt32(scrollHeight * doc.Rect.Width / doc.Rect.Height);
    
            id = doc.AddImageUrl(Url);
          }
        }
        else
        {
          var scrollHeight = doc.GetInfoInt(id, "ScrollHeight");
          var contentHeight = doc.GetInfoInt(id, "ContentHeight");
    
          if (scrollHeight > contentHeight + (PageInsetVertical *2))
          {
            var scrollWidth = doc.GetInfoInt(id, "ScrollWidth");
            doc.Delete(id);
            doc.HtmlOptions.BrowserWidth = Convert.ToInt32(((double)scrollHeight / contentHeight) * scrollWidth);
            id = doc.AddImageUrl(Url);
          }
        }
    
        if (MakeLandscape)
        {
          doc.SetInfo(doc.GetInfoInt(doc.Root, "Pages"), "/Rotate", "90");
        }
    
        using (var ms = new MemoryStream())
        {
          doc.Save(ms);
          if (ms.CanSeek)
          {
            ms.Seek(0, SeekOrigin.Begin);
          }
          return ms.GetBuffer();
        }
      }