首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >调用wkhtmltopdf从HTML生成PDF

调用wkhtmltopdf从HTML生成PDF
EN

Stack Overflow用户
提问于 2009-08-26 01:35:56
回答 11查看 72.2K关注 0票数 54

我正在尝试从HTML文件创建PDF文件。环顾四周后,我发现:wkhtmltopdf是完美的。我需要从ASP.NET服务器调用这个.exe。我尝试过:

代码语言:javascript
复制
    Process p = new Process();
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.FileName = HttpContext.Current.Server.MapPath("wkhtmltopdf.exe");
    p.StartInfo.Arguments = "TestPDF.htm TestPDF.pdf";
    p.Start();
    p.WaitForExit();

在服务器上没有成功创建任何文件。有没有人能给我指个方向?我将wkhtmltopdf.exe文件放在站点的顶级目录中。有没有其他地方应该举行?

编辑:如果谁有更好的解决方案,从html动态创建pdf文件,请让我知道。

EN

回答 11

Stack Overflow用户

发布于 2009-11-09 10:43:38

更新:

我下面的回答是在磁盘上创建pdf文件。然后,我将该文件下载到用户浏览器中。考虑使用下面Hath的答案,让wkhtml2pdf输出到一个流,然后直接发送给用户-这将绕过许多文件权限等问题。

我的原始答案:

确保您为PDF指定了一个可由服务器(我认为通常是NETWORK_SERVICE )上运行的IIS的ASP.NET进程写入的输出路径。

我的代码看起来是这样的(并且它是有效的):

代码语言:javascript
复制
/// <summary>
/// Convert Html page at a given URL to a PDF file using open-source tool wkhtml2pdf
/// </summary>
/// <param name="Url"></param>
/// <param name="outputFilename"></param>
/// <returns></returns>
public static bool HtmlToPdf(string Url, string outputFilename)
{
    // assemble destination PDF file name
    string filename = ConfigurationManager.AppSettings["ExportFilePath"] + "\\" + outputFilename + ".pdf";

    // get proj no for header
    Project project = new Project(int.Parse(outputFilename));

    var p = new System.Diagnostics.Process();
    p.StartInfo.FileName = ConfigurationManager.AppSettings["HtmlToPdfExePath"];

    string switches = "--print-media-type ";
    switches += "--margin-top 4mm --margin-bottom 4mm --margin-right 0mm --margin-left 0mm ";
    switches += "--page-size A4 ";
    switches += "--no-background ";
    switches += "--redirect-delay 100";

    p.StartInfo.Arguments = switches + " " + Url + " " + filename;

    p.StartInfo.UseShellExecute = false; // needs to be false in order to redirect output
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.RedirectStandardInput = true; // redirect all 3, as it should be all 3 or none
    p.StartInfo.WorkingDirectory = StripFilenameFromFullPath(p.StartInfo.FileName);

    p.Start();

    // read the output here...
    string output = p.StandardOutput.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 (not sure about other values, I want a better way to confirm this)
    return (returnCode == 0 || returnCode == 2);
}
票数 51
EN

Stack Overflow用户

发布于 2010-09-10 18:07:57

当我尝试在windows服务中使用msmq时,我也遇到了同样的问题,但由于某些原因,它的速度非常慢。(流程部分)。

这就是最终有效的方法:

代码语言:javascript
复制
private void DoDownload()
{
    var url = Request.Url.GetLeftPart(UriPartial.Authority) + "/CPCDownload.aspx?IsPDF=False?UserID=" + this.CurrentUser.UserID.ToString();
    var file = WKHtmlToPdf(url);
    if (file != null)
    {
        Response.ContentType = "Application/pdf";
        Response.BinaryWrite(file);
        Response.End();
    }
}

public byte[] WKHtmlToPdf(string url)
{
    var fileName = " - ";
    var wkhtmlDir = "C:\\Program Files\\wkhtmltopdf\\";
    var wkhtml = "C:\\Program Files\\wkhtmltopdf\\wkhtmltopdf.exe";
    var p = new Process();

    p.StartInfo.CreateNoWindow = true;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.RedirectStandardInput = true;
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.FileName = wkhtml;
    p.StartInfo.WorkingDirectory = wkhtmlDir;

    string switches = "";
    switches += "--print-media-type ";
    switches += "--margin-top 10mm --margin-bottom 10mm --margin-right 10mm --margin-left 10mm ";
    switches += "--page-size Letter ";
    p.StartInfo.Arguments = switches + " " + url + " " + fileName;
    p.Start();

    //read output
    byte[] buffer = new byte[32768];
    byte[] file;
    using(var ms = new MemoryStream())
    {
        while(true)
        {
            int read =  p.StandardOutput.BaseStream.Read(buffer, 0,buffer.Length);

            if(read <=0)
            {
                break;
            }
            ms.Write(buffer, 0, read);
        }
        file = ms.ToArray();
    }

    // wait or exit
    p.WaitForExit(60000);

    // read the exit code, close process
    int returnCode = p.ExitCode;
    p.Close();

    return returnCode == 0 ? file : null;
}

感谢Graham Ambrose和其他所有人。

票数 41
EN

Stack Overflow用户

发布于 2014-12-23 07:33:32

好了,这是一个古老的问题,但也是一个很好的问题。由于我没有找到一个好的答案,所以我提出了自己的答案:) Also, I've posted this super simple project to GitHub.

下面是一些示例代码:

代码语言:javascript
复制
var pdfData = HtmlToXConverter.ConvertToPdf("<h1>SOO COOL!</h1>");

以下是一些关键点:

  • 无P/Invoke
  • 无创建新进程
  • 无文件系统(全部在内存中)具有智能感知等功能的
  • 本机.NET DLL。
  • 能够生成PDF或PNG DLL
票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1331926

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档