【问题标题】:Tell abcPdf to scale the html to fit on a single pdf page告诉 abcPdf 缩放 html 以适应单个 pdf 页面
【发布时间】:2010-01-25 13:00:51
【问题描述】:

我正在使用 abcPdf 将 HTML 报告转换为 pdf 文件。 pdf 必须是单个横向 A4 页面。

您知道是否有任何方法可以告诉 abcPdf 缩放 HTML 页面以适应 pdf 中的单个页面?我尝试使用Magnify() method,它会缩放内容,但仍会将其分成页面,即使它适合一页。我已经为此苦苦思索了一段时间,想知道是否有人这样做过。

这是我目前正在使用的代码:

public byte[] UrlToPdf(string url, PageOrientation po)
{
    using (Doc theDoc = new Doc())
    {
        // When in landscape mode:
        // We use two transforms to apply a generic 90 degree rotation around
        // the center of the document and rotate the drawing rectangle by the same amount.
        if (po == PageOrientation.Landscape)
        {
            // apply a rotation transform
            double w = theDoc.MediaBox.Width;
            double h = theDoc.MediaBox.Height;
            double l = theDoc.MediaBox.Left;
            double b = theDoc.MediaBox.Bottom;
            theDoc.Transform.Rotate(90, l, b);
            theDoc.Transform.Translate(w, 0);

            // rotate our rectangle
            theDoc.Rect.Width = h;
            theDoc.Rect.Height = w;

            // To change the default orientation of the document we need to apply a rotation to the root page object.
            //By doing this we ensure that every page in the document is viewed rotated.
            int theDocID = Convert.ToInt32(theDoc.GetInfo(theDoc.Root, "Pages"));
            theDoc.SetInfo(theDocID, "/Rotate", "90");
        }

        theDoc.HtmlOptions.PageCacheEnabled = false;
        theDoc.HtmlOptions.AddForms = false;
        theDoc.HtmlOptions.AddLinks = false;
        theDoc.HtmlOptions.AddMovies = false;
        theDoc.HtmlOptions.FontEmbed = false;
        theDoc.HtmlOptions.UseResync = false;
        theDoc.HtmlOptions.UseVideo = false;
        theDoc.HtmlOptions.UseScript = false;
        theDoc.HtmlOptions.HideBackground = false;
        theDoc.HtmlOptions.Timeout = 60000;
        theDoc.HtmlOptions.BrowserWidth = 0;
        theDoc.HtmlOptions.ImageQuality = 101;

        // Add url to document.
        int theID = theDoc.AddImageUrl(url, true, 0, true);
        while (true)
        {
            if (!theDoc.Chainable(theID))
                break;
            theDoc.Page = theDoc.AddPage();
            theID = theDoc.AddImageToChain(theID);
        }
        //Flattening the pages (Whatever that means)
        for (int i = 1; i <= theDoc.PageCount; i++)
        {
            theDoc.PageNumber = i;
            theDoc.Flatten();
        }

        return theDoc.GetData();
    }
}

【问题讨论】:

    标签: .net asp.net abcpdf


    【解决方案1】:

    这就是我解决这个问题的方法。

    首先,我需要将HTML页面的高度传递给pdf生成方法,所以我在要pdf-ed的页面上添加了这个:

    <asp:HiddenField ID="hfHeight" runat="server" />
    

    在后面的代码中:

    protected void Page_Init(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            string scriptKey = "WidhtHeightForPdf";
            if (!Page.ClientScript.IsClientScriptBlockRegistered(scriptKey))
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("<script>")
                    .AppendLine("document.getElementById('" + hfHeight.ClientID + "').value = document.body.clientHeight;")
                    .AppendLine("</script>");
    
                Page.ClientScript.RegisterStartupScript(typeof(Page), scriptKey, sb.ToString());
            }
        }
    }
    

    现在,当我调用 pdf 生成方法时,我可以将 HTML 的高度传递给它。一旦我有了高度,只需计算 pdf“视口”的宽度,以使高度适合 pdf 页面:

    int intHTMLWidth = height.Value * Convert.ToInt32(theDoc.Rect.Width / theDoc.Rect.Height);
    

    然后通过HtmlOptionstheDoc指定BrowserWidth参数:

    theDoc.HtmlOptions.BrowserWidth = intHTMLWidth;
    

    或将网址添加到theDoc时:

    int theID = theDoc.AddImageUrl(url, true, intHTMLWidth, true);
    

    编辑:这解决了问题,所以我将其标记为答案。现在接下来要做的就是根据 HTML 的宽度和高度以 protrait 或横向模式创建 pdf,以便在 pdf 页面上使用最大空间。

    【讨论】:

    【解决方案2】:

    这可能会简单一些

        /// <summary>
        /// Calculate the height of given html
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public int CalculateHeight(string html)
        {
            int id = _Document.AddImageHtml(html);
            int height = (int)(_Document.GetInfoInt(id, "ScrollHeight") * PixelToPointScale);
            _Document.Delete( id );
            return height;
        }
    

    [编辑] 好吧,scrollHeight 使用 ver8 失败了,不过这可以工作

        private int AddImageHtml(string html)
        {
            try
            {
                return _Document.AddImageHtml("<div id='pdfx-div-pdf-frame' class='abcpdf-tag-visible' style='abcpdf-tag-visible: true; border: 1px solid red'>" + html + "</div>");
            }
            catch (Exception ex)
            {
                throw new Exception(html, ex);
            }
        }
    
        private double GetElementHeight(int id)
        {
            abcpdf.XRect[] tagRects = _Document.HtmlOptions.GetTagRects(id);
            string[] tagIds = _Document.HtmlOptions.GetTagIDs(id);
    
            for (int i=0;i<tagRects.Length;i++)
            {
                abcpdf.XRect rect = tagRects[i];
                string tagId = tagIds[i];
                if (string.Equals(tagId, "pdfx-div-pdf-frame", StringComparison.CurrentCultureIgnoreCase))
                {
                    return rect.Height;
                }
            }
            return -1;
        }
    

    【讨论】:

      【解决方案3】:

      如果您使用“Gecko”引擎,该引擎不支持“GetInfoInt”,因此我们需要编写一些 javascript 来获取高度。首先进行虚拟渲染以确定高度,然后将此高度设置为原始 AbcDoc。

      using (var tempDoc = new Doc())
                      {
                          tempDoc.HtmlOptions.Engine = EngineType.Gecko;
                          tempDoc.HtmlOptions.Media = MediaType.Print;
                          tempDoc.HtmlOptions.UseScript = true;
                          if (width.HasValue)
                              tempDoc.HtmlOptions.BrowserWidth = width.Value;
      
                          tempDoc.HtmlOptions.OnLoadScript = " window.onbeforeprint = function () { document.documentElement.abcpdf = Math.max( document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight );}";
                          int theTempID = tempDoc.AddImageHtml(htmlData);
      
                          int height = Convert.ToInt32(tempDoc.HtmlOptions.GetScriptReturn(theTempID));
      
                          tempDoc.Clear();
                          tempDoc.Dispose();
      
                          theDoc.MediaBox.Height = height;
                          theDoc.Rect.String = theDoc.MediaBox.String;
                          theDoc.AddImageHtml(htmlData);
                      }
      

      【讨论】:

        猜你喜欢
        • 2011-11-17
        • 1970-01-01
        • 2015-07-03
        • 1970-01-01
        • 2013-12-31
        • 1970-01-01
        • 1970-01-01
        • 2010-10-07
        相关资源
        最近更新 更多