2

Google マップで場所を表示している Web ページの PDF を作成しようとしています。唯一の問題は、ABCpdf が pdf をレンダリングするまでに Javascript が完全に完了していないことです。不完全です。PDFがレンダリングされる前に、JavaScriptが100%完了するまでABDpdfを待機させるにはどうすればよいですか。これが私がこれまでに試したことです。

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 VisualizationをPDFとしてレンダリングする)。これは、部分的に解決するために使用したトリックです。

まず、JavaScriptを実行する必要がありますDOMContentLoadedload理由はすぐにわかります)。次に、タイマーによってコンテンツを提供する空のページを作成します(ページを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を実行するために必要な時間を正確に予測することはできません。もう1つは、ABCpdfが15秒以内にページを読み込めない場合(デフォルト値ですが、変更できると思います)、例外がスローされるため、遅延を選択するときは注意してください。

お役に立てれば。

于 2012-04-23T06:11:08.833 に答える
2

私の場合、v8 を v9 にアップグレードし、Web ページのサムネイル画像を生成していましたが、オブジェクトの配置に大規模な JavaScript CSS 操作も必要でした。v9 に切り替えたとき、オブジェクトが複製されていることに気付きました (元の位置と js の後に配置されるはずだった位置を示しています)。

私が適用した回避策は、RenderDelay および OneStageRender プロパティを使用して、ページのレンダリングを PDF に処理する方法を変更することでした。500 はミリ秒なので、1/2 秒です。より大きな原因は OneStageRender にあるようです。レンダリングを適切に処理するには、これを無効にする必要がありました。

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 に答える