2013-01-11 59 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输出