2012-04-17 97 views
1

我正在嘗試製作在Google地圖上顯示位置的網頁的pdf。唯一的問題是,在ABCpdf呈現pdf時,Javascript並沒有完全完成。它不完整。在呈現pdf之前,如何讓ABDpdf等到JavaScript完成100%完成。這是我到目前爲止所嘗試的。讓HTML在呈現PDF之前完成Javascript 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(); 
+0

請更具體地說明在其他部分完成之前您希望等待執行哪部分代碼。 – jfriend00 2012-04-17 15:41:16

回答

1

我有一個非常類似的問題(渲染谷歌可視化的PDF)和下面是我用來部分地解決它的伎倆:

首先,你的JavaScript需要在DOMContentLoaded執行,而不是load(你會明白爲什麼就在一瞬間)。接下來創建一個空白頁面,通過定時器爲內容提供服務(您可以使用System.Threading.Thread.Sleep使頁面「等待」一段時間)。

然後在您要呈現爲PDF的頁面上放置一個隱藏圖像,其中包含需要在生成PDF之前執行的JavaScript。 「源」圖像的屬性必須指向你的計時器頁面的URL(在下面的例子中,我指定通過查詢字符串以毫秒爲單位的延遲):

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

請注意,我用visibility: hidden,而不是display: none到隱藏圖像。原因是某些瀏覽器可能無法在圖像可見之前開始加載圖像。

現在會發生的情況是,ABCpdf將等待圖像加載完成,而您的JavaScript已經執行(因爲在load之前啓動DOMContentLoaded,等待所有圖像加載)。

當然,您無法預測您需要多少時間才能執行JavaScript。另一件事是,如果ABCpdf無法在15秒內加載頁面(默認值,但我認爲你可以改變它),它會拋出一個異常,所以選擇延遲時要小心。

希望這會有所幫助。

+1

哇,這一定是我見過的最清晰的解決方法!或者,您可以在文檔中查找'RenderDelay','ABCpdf_RenderWait'或'ABCpdf_go',以獲得更少的男子氣概的方法;) – kizzx2 2012-05-05 04:39:37

+0

@ kizzx2謝謝,我們將研究它:-) – volpav 2012-05-05 22:25:36

-1

嘗試使你的腳本塊到一個JavaScript函數,並呼籲從document.ready()功能該功能在你的文件的頂部。我假設你正在使用jQuery。 ready()函數將確保所有頁面元素在它調用其正文中的任何函數之前已穩定。

1

在我的情況下,我們將v8升級到v9,並生成一個網頁的縮略圖圖像,這也需要廣泛的JavaScript CSS操作來定位對象。當我們切換到v9時,我們注意到對象被複制(顯示在它們的原始位置以及它們應該位於js之後的位置)。

我應用的解決方法是使用RenderDelay和OneStageRender屬性來更改將頁面呈現處理爲PDF的方式。 500是毫秒,所以1/2秒。更大的罪魁禍首似乎是OneStageRender。必須禁用該功能才能正確處理渲染。

doc.SetInfo(0, "RenderDelay", "500") 
doc.SetInfo(0, "OneStageRender", 0)