2013-01-11 60 views
0

我使用wkhtmltopdf.exe使用下面的代碼生成PDF。在c#中使用wkhtmltopdf.exe生成PDF

string url = HttpContext.Current.Request.Url.AbsoluteUri; 

     //string[] strarry = sPath.Split('/'); 
     //int lengh = strarry.Length; 

    var pdfUrl = HtmlToPdf(pdfOutputLocation: "~/PDF/", outputFilenamePrefix: "DT", urls: new string[] { url }); 

     WebClient req = new WebClient(); 
     HttpResponse response = HttpContext.Current.Response; 
     response.Clear(); 
     response.ClearContent(); 
     response.ClearHeaders(); 
     response.Buffer = true; 
     Response.ContentType = "application/pdf"; 
     response.AddHeader("Content-Disposition", "attachment;filename=\"" + pdfUrl.ToString().Substring(6) + "\""); 
     byte[] data = req.DownloadData(Server.MapPath(pdfUrl.ToString())); 
     response.BinaryWrite(data); 
     File.Delete(Server.MapPath(pdfUrl.ToString())); 
     response.End(); 

public static string HtmlToPdf(string pdfOutputLocation, string outputFilenamePrefix, string[] urls, 
string[] options = null, 
string pdfHtmlToPdfExePath = "C:\\Program Files\\wkhtmltopdf\\wkhtmltopdf.exe") 
    { 
     string urlsSeparatedBySpaces = string.Empty; 
     try 
     { 
      //Determine inputs 
      if ((urls == null) || (urls.Length == 0)) 
       throw new Exception("No input URLs provided for HtmlToPdf"); 
      else 
       urlsSeparatedBySpaces = String.Join(" ", urls); //Concatenate URLs 

      string outputFolder = pdfOutputLocation; 
      string outputFilename = outputFilenamePrefix + "_" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss-fff") + ".PDF"; // assemble destination PDF file name 

      var p = new System.Diagnostics.Process() 
      { 
       StartInfo = 
       { 
        FileName = pdfHtmlToPdfExePath, 
        Arguments = ((options == null) ? "" : String.Join(" ", options)) + " " + urlsSeparatedBySpaces + " " + outputFilename, 
        UseShellExecute = false, // needs to be false in order to redirect output 
        RedirectStandardOutput = true, 
        RedirectStandardError = true, 
        RedirectStandardInput = true, // redirect all 3, as it should be all 3 or none 
        WorkingDirectory = HttpContext.Current.Server.MapPath(outputFolder) 
       } 
      }; 

      p.Start(); 

      // read the output here... 
      var output = p.StandardOutput.ReadToEnd(); 
      var errorOutput = p.StandardError.ReadToEnd(); 

      // ...then wait n milliseconds for exit (as after exit, it can't read the output) 
      p.WaitForExit(60000); 

      // read the exit code, close process 
      int returnCode = p.ExitCode; 
      p.Close(); 

      // if 0 or 2, it worked so return path of pdf 
      if ((returnCode == 0) || (returnCode == 2)) 
       return outputFolder + outputFilename; 
      else 
       throw new Exception(errorOutput); 



      //Response.ContentType = "application/pdf"; 
      //Response.AddHeader("content-length", theData.Length.ToString()); 
      //if (Request.QueryString["attachment"] != null) 
      // Response.AddHeader("content-disposition", "attachment; filename=ExampleSite.pdf"); 
      //else 
      // Response.AddHeader("content-disposition", "inline; filename=ExampleSite.pdf"); 
      //Response.BinaryWrite(theData); 
      //HttpContext.Current.ApplicationInstance.CompleteRequest(); 
     } 
     catch (Exception exc) 
     { 
      throw new Exception("Problem generating PDF from HTML, URLs: " + urlsSeparatedBySpaces + ", outputFilename: " + outputFilenamePrefix, exc); 
     } 
    } 

從上面的代碼的PDF生成well.but我有兩頁與登錄和註銷User.for例如相同的URL可以說www.xyz/pdf/brason 。同一個URL用於LogIn和LogOut User,但內容將根據用戶登錄或註銷而有所不同。

現在,當我登錄並嘗試使用上述代碼生成PDF時,它總是向我顯示註銷用戶頁面的內容。我不確定我該如何解決此問題。

回答

1

我想如果我理解正確這是因爲調用頁面的wkhtmltopdf沒有登錄。Wkhtmltopdf就像創建一個新的隱身瀏覽器窗口沒有任何登錄cookie /會話,所以頁面正確認爲它沒有登錄。您可以通過調試服務器在wkhtmltopdf調用時獲取的請求來進行maby check。

如果這是問題,可能很難解決。解決方案取決於您的登錄系統以及您可以採取什麼措施來解決問題。如果您可以使用cookie複製登錄名,則可以自行設置登錄cookie,請參閱http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf_0.10.0_rc2-doc.html#Page%20Options以獲取有關如何設置cookie的更多信息。

另一種選擇是首先從系統創建一個請求,返回已登錄的HTML,然後將其保存到文件/流並將該文件/流提供給wkhtmltopdf(我猜你可以使用HttpContext .Current.Request什麼的,我不知道)。

另一個解決方法是創建登錄頁面的重複頁面,該頁面看起來與登錄頁面完全相同,但實際上不是 - 該頁面僅用於愚弄wkhtmltopdf。就像www.xyz/pdf/brason?foolwkhtmltopdf=true然後通過調用像if(url.ToLower() == "www.xyz/pdf/brason") {url="www.xyz/pdf/brason?foolwkhtmltopdf=true"; }這樣的東西來使用它。這可能是安全風險,具體取決於顯示的信息。

希望這會有所幫助!

+0

謝謝... Nenotlep –

0

我認爲你需要在轉換爲html之前保存頁面的輸出。因爲這直接調用網址,當它調用它時,你沒有登錄轉換爲PDF獲取其請求的響應 我有同樣的問題試圖將網頁轉換爲PDF格式,但填寫的值,所以我保存響應爲HTML並給了wkhtmltopdf作爲參數保存路徑

Response.ContentType = "application/pdf"; 
     Response.AddHeader("content-disposition", "attachment;filename=TestPage.pdf"); 
     Response.Cache.SetCacheability(HttpCacheability.NoCache); 
     StringWriter sw = new StringWriter(); 
     HtmlTextWriter hw = new HtmlTextWriter(sw); 
     this.Page.RenderControl(hw); 
     StringReader sr = new StringReader(sw.ToString()); 
     string htmlpath =Server.MapPath("~/htmloutput.html"); 
     if (File.Exists(htmlpath)) 
     { 
      File.Delete(htmlpath); 

     } 

     File.Create(htmlpath).Dispose(); 
     using (TextWriter tw = new StreamWriter(htmlpath)) 
     { 
      tw.WriteLine(sw.ToString()); 
      tw.Close(); 
     } 

     string path = Server.MapPath("~/wkhtmltopdf-page.pdf"); 
     PdfConvert.ConvertHtmlToPdf(new Codaxy.WkHtmlToPdf.PdfDocument 
     { 
      Url = htmlpath, 
      HeaderLeft = "[title]", 
      HeaderRight = "[date] [time]", 
      FooterCenter = "Page [page] of [topage]" 

     }, new PdfOutput 
     { 

      OutputFilePath = path 

     }); 

你可以調用這個按鈕的點擊事件。只在asp.net webforms上測試過。在asp.net mvc上,你需要一些其他方式來獲得意見html輸出