如何在 ASP.net 中使用 wkhtmltopdf.exe

发布于 2024-09-01 06:50:52 字数 493 浏览 8 评论 0原文

经过 10 个小时并尝试了其他 4 个 HTML 转 PDF 工具后,我快要爆炸了。

wkhtmltopdf 听起来是一个很好的解决方案...问题是我无法执行进程具有来自 asp.net 的足够权限,所以...

Process.Start("wkhtmltopdf.exe","http://www.google.com google.pdf");

启动但不执行任何操作。

有没有一种简单的方法可以:

-a)允许asp.net启动进程(实际上可以做某事)或
-b) 将 wkhtmltopdf.exe 编译/包装/任何内容转换为我可以从 C# 使用的东西,如下所示: WkHtmlToPdf.Save("http://www.google.com", "google.pdf");

After 10 hours and trying 4 other HTML to PDF tools I'm about ready to explode.

wkhtmltopdf sounds like an excellent solution...the problem is that I can't execute a process with enough permissions from asp.net so...

Process.Start("wkhtmltopdf.exe","http://www.google.com google.pdf");

starts but doesn't do anything.

Is there an easy way to either:

-a) allow asp.net to start processes (that can actually do something) or
-b) compile/wrap/whatever wkhtmltopdf.exe into somthing I can use from C# like this: WkHtmlToPdf.Save("http://www.google.com", "google.pdf");

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一场春暖 2024-09-08 06:50:52

您还可以使用 Pechkin

.NET Wrapper for WkHtmlToPdf DLL,使用 Webkit 引擎的库
将 HTML 页面转换为 PDF。

Nuget 包:

Pechkin.Synchronized

佩希金

You could also use Pechkin

.NET Wrapper for WkHtmlToPdf DLL, library that uses Webkit engine to
convert HTML pages to PDF.

Nuget packages:

Pechkin.Synchronized

Pechkin

情场扛把子 2024-09-08 06:50:52

我刚刚启动了一个新项目,为 wkhtmltopdf 提供 C# P/Invoke 包装器。

您可以在以下位置查看我的代码:https://github.com/pruiz/WkHtmlToXSharp

问候。

I just started a new project to provide a C# P/Invoke wrapper around wkhtmltopdf.

You can checkout my code at: https://github.com/pruiz/WkHtmlToXSharp

Greets.

早茶月光 2024-09-08 06:50:52

感谢 Paul,我找到了很好的wrapper 由 Codaxy 编写,也可以通过 NuGet

经过几次试验后,我已经管理了这个 MVC 操作,它立即创建 PDF 文件并将其作为流返回:

public ActionResult Pdf(string url, string filename)
{
    MemoryStream memory = new MemoryStream();
    PdfDocument document = new PdfDocument() { Url = url };
    PdfOutput output = new PdfOutput() { OutputStream = memory };

    PdfConvert.ConvertHtmlToPdf(document, output);
    memory.Position = 0;

    return File(memory, "application/pdf", Server.UrlEncode(filename));
}

这里,Pdf* 类已在包装器中实现,具有漂亮、干净的代码,不幸的是缺乏文档。

在转换器中,URL 将被转换为 PDF,存储在临时文件中,复制到我们作为参数给出的流中,然后删除 PDF 文件。

最后,我们必须将流作为 FileStreamResult 推送。

不要忘记将输出流的位置设置为零,否则您将看到下载的 PDF 文件大小为零字节。

Thanks to Paul, I have found the good wrapper written by Codaxy, which can also be easily downloaded via NuGet.

After a few trials, I have managed this MVC action, that instantly creates and returns the PDF file as a stream:

public ActionResult Pdf(string url, string filename)
{
    MemoryStream memory = new MemoryStream();
    PdfDocument document = new PdfDocument() { Url = url };
    PdfOutput output = new PdfOutput() { OutputStream = memory };

    PdfConvert.ConvertHtmlToPdf(document, output);
    memory.Position = 0;

    return File(memory, "application/pdf", Server.UrlEncode(filename));
}

Here, the Pdf* classes have been implemented in the wrapper, with a nice, clean code, unfortunately lacking documentation.

Within the converter, the URL will be converted to a PDF, stored in a temporary file, copied to the stream that we have given as parameter, and afterwards the PDF file is deleted.

Finally, we have to push the stream as FileStreamResult.

Do not forget to set the output stream's Position to zero, otherwise you will see PDF files being downloaded as zero bytes of size.

香橙ぽ 2024-09-08 06:50:52

这是我使用的实际代码。请随意编辑它以消除一些气味和其他可怕的东西......我知道它不是那么好。

using System;
using System.Diagnostics;
using System.IO;
using System.Web;
using System.Web.UI;

public partial class utilities_getPDF : Page
{
    protected void Page_Load(Object sender, EventArgs e)
    {
        string fileName = WKHtmlToPdf(myURL);

        if (!string.IsNullOrEmpty(fileName))
        {
            string file = Server.MapPath("~\\utilities\\GeneratedPDFs\\" + fileName);
            if (File.Exists(file))
            {
                var openFile = File.OpenRead(file);
                // copy the stream (thanks to http://stackoverflow.com/questions/230128/best-way-to-copy-between-two-stream-instances-c)
                byte[] buffer = new byte[32768];
                while (true)
                {
                    int read = openFile.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                    {
                        break;
                    }
                    Response.OutputStream.Write(buffer, 0, read);
                }
                openFile.Close();
                openFile.Dispose();

                File.Delete(file);
            }
        }
    }

    public string WKHtmlToPdf(string Url)
    {
        var p = new Process();

        string switches = "";
        switches += "--print-media-type ";
        switches += "--margin-top 10mm --margin-bottom 10mm --margin-right 10mm --margin-left 10mm ";
        switches += "--page-size Letter ";
        // waits for a javascript redirect it there is one
        switches += "--redirect-delay 100";

        // Utils.GenerateGloballyUniuqueFileName takes the extension from
        // basically returns a filename and prepends a GUID to it (and checks for some other stuff too)
        string fileName = Utils.GenerateGloballyUniqueFileName("pdf.pdf");

        var startInfo = new ProcessStartInfo
                        {
                            FileName = Server.MapPath("~\\utilities\\PDF\\wkhtmltopdf.exe"),
                            Arguments = switches + " " + Url + " \"" +
                                        "../GeneratedPDFs/" + fileName
                                        + "\"",
                            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 = Server.MapPath("~\\utilities\\PDF")
                        };
        p.StartInfo = startInfo;
        p.Start();

        // doesn't work correctly...
        // read the output here...
        // string output = p.StandardOutput.ReadToEnd();

        //  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, it worked
        return (returnCode == 0) ? fileName : null;
    }
}

Here is the actual code I used. Please feel free to edit this to get rid of some of the smells and other terribleness...I know its not that great.

using System;
using System.Diagnostics;
using System.IO;
using System.Web;
using System.Web.UI;

public partial class utilities_getPDF : Page
{
    protected void Page_Load(Object sender, EventArgs e)
    {
        string fileName = WKHtmlToPdf(myURL);

        if (!string.IsNullOrEmpty(fileName))
        {
            string file = Server.MapPath("~\\utilities\\GeneratedPDFs\\" + fileName);
            if (File.Exists(file))
            {
                var openFile = File.OpenRead(file);
                // copy the stream (thanks to http://stackoverflow.com/questions/230128/best-way-to-copy-between-two-stream-instances-c)
                byte[] buffer = new byte[32768];
                while (true)
                {
                    int read = openFile.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                    {
                        break;
                    }
                    Response.OutputStream.Write(buffer, 0, read);
                }
                openFile.Close();
                openFile.Dispose();

                File.Delete(file);
            }
        }
    }

    public string WKHtmlToPdf(string Url)
    {
        var p = new Process();

        string switches = "";
        switches += "--print-media-type ";
        switches += "--margin-top 10mm --margin-bottom 10mm --margin-right 10mm --margin-left 10mm ";
        switches += "--page-size Letter ";
        // waits for a javascript redirect it there is one
        switches += "--redirect-delay 100";

        // Utils.GenerateGloballyUniuqueFileName takes the extension from
        // basically returns a filename and prepends a GUID to it (and checks for some other stuff too)
        string fileName = Utils.GenerateGloballyUniqueFileName("pdf.pdf");

        var startInfo = new ProcessStartInfo
                        {
                            FileName = Server.MapPath("~\\utilities\\PDF\\wkhtmltopdf.exe"),
                            Arguments = switches + " " + Url + " \"" +
                                        "../GeneratedPDFs/" + fileName
                                        + "\"",
                            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 = Server.MapPath("~\\utilities\\PDF")
                        };
        p.StartInfo = startInfo;
        p.Start();

        // doesn't work correctly...
        // read the output here...
        // string output = p.StandardOutput.ReadToEnd();

        //  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, it worked
        return (returnCode == 0) ? fileName : null;
    }
}
可是我不能没有你 2024-09-08 06:50:52

我无法发表评论,所以我将其发布为上述答案的评论的“答案”如何在 ASP.net 中使用 wkhtmltopdf.exe

如果 --redirect-delay 不起作用,请尝试 --javascript-delay< /代码>
请参阅此处了解所有选项: https://github.com/antialize/wkhtmltopdf/blob /master/README_WKHTMLTOPDF

或执行 wkhtmltopdf -H 以获得扩展帮助(据我所知,输出与上面的链接相同)。

I can't comment so I post this as an 'answer' to the comments of above answer How to use wkhtmltopdf.exe in ASP.net

If --redirect-delay doesn't work, try --javascript-delay
See here for all the options: https://github.com/antialize/wkhtmltopdf/blob/master/README_WKHTMLTOPDF

Or do wkhtmltopdf -H for extended help (afaik same output as above link).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文