在c#中使用wkhtmltopdf.exe生成PDF

本文关键字:exe 生成 PDF wkhtmltopdf | 更新日期: 2023-09-27 17:51:15

我正在使用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生成良好。但我有两个页面与登录和注销用户相同的URL。例如,让我们说www.xyz/pdf/brason。这个相同的URL用于登录和注销用户,但内容将根据用户登录或注销而不同。

现在当我登录并尝试使用上面的代码生成PDF时,它总是向我显示登出用户页面的内容。我不知道如何解决这个问题。

在c#中使用wkhtmltopdf.exe生成PDF

我想如果我理解正确,这是因为调用页面的wkhtmltopdf没有登录。Wkhtmltopdf有点像创建一个新的隐身浏览器窗口,没有任何登录cookie/会话,所以页面正确地认为它没有登录。您可以通过调试wkhtmltopdf调用时服务器收到的请求来检查。

如果这是问题,它可能很难解决。解决方案取决于您的登录系统以及您可以做些什么来解决这个问题。如果您可以通过使用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"; }。这可能存在安全风险,具体取决于所显示的信息。

希望这对你有帮助!

我认为在转换为html之前需要保存页面的输出。因为这直接调用url,你没有登录,当它调用它转换为pdf为它的请求得到的响应我有同样的问题,试图将一个webform转换为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输出