如何在 ASP.net 中使用 wkhtmltopdf.exe [重复]

Posted

技术标签:

【中文标题】如何在 ASP.net 中使用 wkhtmltopdf.exe [重复]【英文标题】:How to use wkhtmltopdf.exe in ASP.net [duplicate] 【发布时间】:2011-02-17 00:45:11 【问题描述】:

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

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

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

启动但不执行任何操作。

有没有简单的方法:

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

【问题讨论】:

这不是一个好主意。集成模式下的 IIS7 禁止这样做,包括模拟。 【参考方案1】:

你也可以使用Pechkin

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

Nuget 包:

Pechkin.Synchronized

Pechkin

【讨论】:

在这么多年之后将其标记为已接受,因为我只需要在一个新项目中再次使用 wkhtmltopdf 并且 Pechkin 工作得很好! 我在使用 pechkin 或 Codaxy 甚至 WkhtmlXSharp 时遇到问题,它们都无法正确显示泰语字体 (Utf-8) 或 unicode 字体。在使用 itextsharp 和 exe 时不会出现这个问题 @DavidMurdoch 您在部署新代码时是否遇到任何文件锁定错误?如果我理解正确,Pechkin 使用本机 dll (WkHtmlToPdf),并且当您上传新文件时,本机 dll 可能不会作为您的托管 dll 卸载?【参考方案2】:

感谢Paul,找到了Codaxy写的不错的wrapper,也可以通过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 文件大小为零。

【讨论】:

为了直接在网页浏览器上通过MVC ActionResult输出PDF流,@endy-tjahjono 通过here展示了一个很好的方法 它工作得很好,但是当我尝试使用标题时挂起(直接使用命令行工具可以正常工作)。 @marquito:你的意思是 HTML5 中的“header”标签吗?我没有任何经验,但是您是否尝试将其替换为一个好老朋友“div”? @BoltThunder 我的意思是“标题”,就像使用 --header-html 修饰符一样。当路径错误并且无法检索标头时,它只会挂起(而不是插入空白标头,例如) 行“return File(memory, "application/pdf", Server.UrlEncode(filename));"正在给我“System.IO.File 是一种类型,但它被用作变量。”【参考方案3】:

我无法发表评论,因此我将其发布为上述答案 How to use wkhtmltopdf.exe in ASP.net 的 cmets 的“答案”

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

或通过wkhtmltopdf -H 获取扩展帮助(afaik 与上述链接的输出相同)。

【讨论】:

【参考方案4】:

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

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

问候。

【讨论】:

哇,看起来很漂亮。感谢分享! 我在使用 MultiplexingConverter 时遇到错误,例如“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。”有没有办法防止这个错误? 我的图片没有嵌入到 pdf 中。图像应显示的位置没有显示任何内容。我检查了它是否是由于图像的相对 url 而发生的,并将其转换为绝对的。仍然没有成功。什么会起作用? 我和布伦南有同样的问题。前几次尝试运行良好,但随后崩溃,我必须重新启动网络服务器才能使其再次运行。有什么建议吗? 他们正在研究一种解决方法...code.google.com/p/wkhtmltopdf/issues/…【参考方案5】:

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

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://***.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;
    

【讨论】:

这不是“如果为 0 或 2,则有效”。它仅在 0 时有效。其他值: 1:(或 8?)EXIT_ERROR 的一般故障代码值。 2:错误 404,未找到(和空 PDF)。 3:错误401,未经授权。根据 unix 规范,进程返回的 0 以外的任何值都表示某种错误。 Windows 程序也是如此。 谢谢,+1 更正。代码(和 cmets)最初来自 ***.com/questions/1331926/asp-net-calling-exe/… 我已经尝试了 0.99 和较新的 RC,但它们似乎都不支持 --redirect-delay - 有什么想法吗?你用的是什么版本?它快把我逼疯了!除了不等待我对 laod 的 ajax 调用之外,它工作得很好。 我不太确定我使用的版本是否真的对重定向延迟开关做了任何事情(我从其他人那里复制了代码)。如果 wkhtmltopdf 能够运行 javascript/XHR,请确保没有 JS 错误。另外,请尝试确保代码运行之前 window.onload. 最后你可以尝试做这样的事情:(看看:code.google.com/p/wkhtmltopdf/issues/detail?id=315)` --run-script (function()var d = new Date()+10000;while (new Date()

以上是关于如何在 ASP.net 中使用 wkhtmltopdf.exe [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 javascript 将图像保存在文件夹中? ASP.NET

如何在asp.net c# web应用程序中使用asp.net vb页面

如何在 ASP.NET Core 3.1 中使用 Java?

如何在 asp.net 中使用 gmail api [重复]

如何在使用 HttpClient 使用 Asp Net Web Api 的 Asp Net Mvc 中提供实时数据?

如何在 ASP.NET Core 中使用 SqlClient?