2

我正在尝试制作在 Google 地图上显示位置的网页的 pdf。唯一的问题是,在 ABCpdf 呈现 pdf 时,Javascript 还没有完全完成。它不完整。如何让 ABDpdf 等到 javascript 100% 完成后再呈现 pdf。这是我到目前为止所尝试的。

Doc theDoc = new Doc();
            string theURL = url;
            // Set HTML options
            theDoc.HtmlOptions.AddLinks = true;
            theDoc.HtmlOptions.UseScript = true;
            theDoc.HtmlOptions.PageCacheEnabled = false;
            //theDoc.HtmlOptions.Engine = EngineType.Gecko;
            // JavaScript is used to extract all links from the page

            theDoc.HtmlOptions.OnLoadScript = "var hrefCollection = document.all.tags(\"a\");" +
              "var allLinks = \"\";" +
              "for(i = 0; i < hrefCollection.length; ++i) {" +
              "if (i > 0)" +
              "  allLinks += \",\";" +
              "allLinks += hrefCollection.item(i).href;" +
              "};" +
              "document.documentElement.abcpdf = allLinks;";
            // Array of links - start with base URL
            theDoc.HtmlOptions.OnLoadScript = "(function(){window.ABCpdf_go = false; setTimeout(function(){window.ABCpdf_go = true;}, 1000);})();";
            ArrayList links = new ArrayList();
            links.Add(theURL);
            for (int i = 0; i < links.Count; i++)
            {
                // Stop if we render more than 20 pages
                if (theDoc.PageCount > 20)
                    break;
                // Add page
                theDoc.Page = theDoc.AddPage();
                int theID = theDoc.AddImageUrl(links[i] as string);
                // Links from the rendered page
                string allLinks = theDoc.HtmlOptions.GetScriptReturn(theID);
                string[] newLinks = allLinks.Split(new char[] { ',' });
                foreach (string link in newLinks)
                {
                    // Check to see if we allready rendered this page
                    if (links.BinarySearch(link) < 0)
                    {
                        // Skip links inside the page
                        int pos = link.IndexOf("#");
                        if (!(pos > 0 && links.BinarySearch(link.Substring(0, pos)) >= 0))
                        {
                            if (link.StartsWith(theURL))
                            {
                                links.Add(link);
                            }
                        }
                    }
                }
                // Add other pages
                while (true)
                {
                    theDoc.FrameRect();
                    if (!theDoc.Chainable(theID))
                        break;
                    theDoc.Page = theDoc.AddPage();
                    theID = theDoc.AddImageToChain(theID);
                }
            }
            // Link pages together
            theDoc.HtmlOptions.LinkPages();
            // Flatten all pages
            for (int i = 1; i <= theDoc.PageCount; i++)
            {
                theDoc.PageNumber = i;
                theDoc.Flatten();
            }

            byte[] theData = theDoc.GetData();

            Response.Buffer = false; //new
            Response.Clear();
            //Response.ContentEncoding = Encoding.Default;
            Response.ClearContent(); //new
            Response.ClearHeaders(); //new
            Response.ContentType = "application/pdf"; //new
            Response.AddHeader("Content-Disposition", "attachment; filename=farts");

            Response.AddHeader("content-length", theData.Length.ToString());
            //Response.ContentType = "application/pdf";
            Response.BinaryWrite(theData);
            Response.End();

            theDoc.Clear();
4

3 回答 3

3

我有一个非常相似的问题(将 Google 可视化呈现为 PDF),这是我用来部分解决它的技巧:

首先,你的 JavaScript 需要被执行DOMContentLoaded而不是被执行load(你马上就会明白为什么)。接下来创建一个空页面,该页面将通过计时器提供内容(您可以使用System.Threading.Thread.Sleep让页面“等待”一段时间)。

然后在要呈现为 PDF 的页面上放置一个隐藏图像,其中包含需要在生成 PDF 之前执行的 JavaScript。图像的“src”属性必须有一个指向您的计时器页面的 URL(在以下示例中,我通过查询字符串指定延迟以毫秒为单位):

<img src="Timer.aspx?Delay=1000" style="width: 1px; height: 1px; visibility: hidden" />

请注意,我使用visibility: hidden而不是display: none隐藏图像。原因是某些浏览器在图像可见之前可能不会开始加载图像。

现在将会发生的是 ABCpdf 将等到图像被加载,而您的 JavaScript 已经在执行(因为在它DOMContentLoaded之前被触发load,直到所有图像都被加载)。

当然,您无法准确预测执行 JavaScript 需要多少时间。另一件事是,如果 ABCpdf 无法在 15 秒内加载页面(默认值,但我认为您可以更改它),它将引发异常,因此在选择延迟时要小心。

希望这可以帮助。

于 2012-04-23T06:11:08.833 回答
2

在我的例子中,我们将 v8 升级到 v9 并生成网页的缩略图,这也需要大量的 javascript CSS 操作来进行对象定位。当我们切换到 v9 时,我们注意到对象被复制了(显示在它们的原始位置和它们应该位于 js 之后的位置)。

The workaround that I applied was using the RenderDelay and OneStageRender properties to change how the page rendering is handled to PDF. The 500 is ms, so 1/2 second. The bigger culprit seemed to be the OneStageRender. That had to be disabled in order for rendering to handle properly.

doc.SetInfo(0, "RenderDelay", "500")
doc.SetInfo(0, "OneStageRender", 0)
于 2016-09-16T12:46:03.867 回答
-1

document.ready()尝试将您的脚本块变成一个 javascript 函数,然后从文件顶部的函数中调用该函数。我假设您正在使用 jQuery。该ready()函数将确保所有页面元素在调用其主体中的任何函数之前都已稳定。

于 2012-04-17T15:42:23.747 回答