【问题标题】:how to pass html as a string using wkhtmltopdf?如何使用 wkhtmltopdf 将 html 作为字符串传递?
【发布时间】:2011-01-10 20:48:13
【问题描述】:

如何使用 asp.net、c# 将 html 作为字符串而不是 wkhtmltopdf 中的 url 传递?

【问题讨论】:

  • 重定向标准输入并以这种方式传递字符串可能是最简单的。您也可以将文本写入文件(当然,这不会很好地扩展)。
  • 你能举个例子吗?

标签: c# asp.net wkhtmltopdf


【解决方案1】:

STDIn 和 STDOut 在此示例中已被重定向,因此您根本不需要文件。

public static class Printer
{
    public const string HtmlToPdfExePath = "wkhtmltopdf.exe";

    public static bool GeneratePdf(string commandLocation, StreamReader html, Stream pdf, Size pageSize)
    {
        Process p;
        StreamWriter stdin;
        ProcessStartInfo psi = new ProcessStartInfo();

        psi.FileName = Path.Combine(commandLocation, HtmlToPdfExePath);
        psi.WorkingDirectory = Path.GetDirectoryName(psi.FileName);

        // run the conversion utility
        psi.UseShellExecute = false;
        psi.CreateNoWindow = true;
        psi.RedirectStandardInput = true;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardError = true;

        // note: that we tell wkhtmltopdf to be quiet and not run scripts
        psi.Arguments = "-q -n --disable-smart-shrinking " + (pageSize.IsEmpty? "" : "--page-width " + pageSize.Width +  "mm --page-height " + pageSize.Height + "mm") + " - -";

        p = Process.Start(psi);

        try {
            stdin = p.StandardInput;
            stdin.AutoFlush = true;
            stdin.Write(html.ReadToEnd());
            stdin.Dispose();

            CopyStream(p.StandardOutput.BaseStream, pdf);
            p.StandardOutput.Close();
            pdf.Position = 0;

            p.WaitForExit(10000);

            return true;
        } catch {
            return false;

        } finally {
            p.Dispose();
        }
    }

    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[32768];
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0) {
            output.Write(buffer, 0, read);
        }
    }
}

【讨论】:

  • 不需要CloseDispose进程,它做同样的事情。只需处置它,或将其放入 using 构造中。 Streams 也是如此。
  • +1 很棒的帖子,我最近用类似的代码写过:megustaulises.com/2012/12/…
  • 很棒的帖子,帮助很大
  • 论点末尾的`--`的目的是什么?我知道它与输出到 STDOUT 有关,但这是 wkhtmltopdf 构造,还是适用于任何命令行?
  • @Walter Stabosz 看到这里code.google.com/p/wkhtmltopdf/wiki/Usage。 Using - 告诉 wkhtmltopdf 使用标准流。
【解决方案2】:

重定向 STDIN 可能是完成您想要做的最简单的方法。

使用 wkhtmltopdf(在 ASP.Net 中)重定向 STDIN 的一种方法如下:

    private void WritePDF(string HTML)
    {
        string inFileName,
                outFileName,
                tempPath;
        Process p;
        System.IO.StreamWriter stdin;
        ProcessStartInfo psi = new ProcessStartInfo();

        tempPath = Request.PhysicalApplicationPath + "temp\\";
        inFileName = Session.SessionID + ".htm";
        outFileName = Session.SessionID + ".pdf";

        // run the conversion utility
        psi.UseShellExecute = false;
        psi.FileName = "c:\\Program Files (x86)\\wkhtmltopdf\\wkhtmltopdf.exe";
        psi.CreateNoWindow = true;
        psi.RedirectStandardInput = true;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardError = true;

        // note that we tell wkhtmltopdf to be quiet and not run scripts
        // NOTE: I couldn't figure out a way to get both stdin and stdout redirected so we have to write to a file and then clean up afterwards
        psi.Arguments = "-q -n - " + tempPath + outFileName;

        p = Process.Start(psi);

        try
        {
            stdin = p.StandardInput;
            stdin.AutoFlush = true;

            stdin.Write(HTML);
            stdin.Close();

            if (p.WaitForExit(15000))
            {
                // NOTE: the application hangs when we use WriteFile (due to the Delete below?); this works
                Response.BinaryWrite(System.IO.File.ReadAllBytes(tempPath + outFileName));
                //Response.WriteFile(tempPath + outFileName);
            }
        }
        finally
        {
            p.Close();
            p.Dispose();
        }

        // delete the pdf
        System.IO.File.Delete(tempPath + outFileName);
    }

请注意,上面的代码假定您的应用程序目录中有一个 temp 目录。此外,您必须为运行 IIS 进程时使用的用户帐户显式启用对该目录的写入访问权限。

【讨论】:

  • 我不能让它与引用的图像和样式表一起工作。这可能吗?当我使用磁盘上的文件运行命令行时,它可以工作。
  • @smerlung 确保 Web 应用可以访问您引用的文件。从命令行运行时,您以登录名运行;从 Web 服务器运行时,您以 Web 服务器登录名运行,它可能无法访问您正在使用的文件。此外,请确保文件的路径从该位置也有意义。例如,如果您引用 ..\styles\style.css,则需要有一个 styles 目录,位于您运行程序的“上方”,其中包含 style.css 文件。
  • 我通过使用绝对路径让它工作。但这不是很好。我明白你的意思,但我的问题是我不明白进程在哪里“运行”。我为 WorkingDirectory 尝试了不同的选项,但无法弄清楚?
【解决方案3】:

我知道这是一篇较旧的帖子,但我希望未来的开发人员能够使用此选项。我也有同样的需求,而仅仅为了在 Web 应用程序中获取 PDF 而必须启动后台进程的想法太糟糕了。

这是另一个选项:https://github.com/TimothyKhouri/WkHtmlToXDotNet

它是 wkhtmltopdf 的 .NET 原生包装器。

这里的示例代码:

var pdfData = HtmlToXConverter.ConvertToPdf("<h1>COOOL!</h1>");

请注意,目前它不是线程安全的 - 我正在努力。因此,只需使用监视器或其他东西或锁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    相关资源
    最近更新 更多