如何使用wkHtmltoPdf从C#中的statcic html文件生成PDf文件

时间:2012-09-21 06:29:42

标签: c# wkhtmltopdf

有人可以建议如何在C#Console应用程序中使用wkhtmltopdf从静态html文件生成PDF文件吗?

wkhtmltopdf - http://code.google.com/p/wkhtmltopdf/

我试过下载ibwkhtmltox-0.11.0_rc1 Windows静态库(i368) 但不能将其dll包含在我的c#console应用程序中。

任何代码示例都会有所帮助

4 个答案:

答案 0 :(得分:6)

查看这个项目github.com/gmanny/Pechkin,它是wkhtmlpdf的包装,但由于它不是作为可执行文件运行,因此您应该更容易在共享主机上运行它。

答案 1 :(得分:3)

我是通过Pechkin的C#端口使用WkHtmlToPdf实现的 - 我到目前为止看到了一些很好的结果(除了在使用SSL从站点调用动态生成的PDF时出现一个相当奇怪的问题)但是对于更基本的实现它很棒!使用NuGet将Pechkin加入您的项目,然后使用以下代码!

byte[] pdf = new Pechkin.Synchronized.SynchronizedPechkin(
new Pechkin.GlobalConfig()).Convert(
    new Pechkin.ObjectConfig()
   .SetLoadImages(true)
   .SetPrintBackground(true)
   .SetScreenMediaType(true)
   .SetCreateExternalLinks(true), html);

using (FileStream file = System.IO.File.Create(@"C:\TEMP\Output.pdf"))
{
    file.Write(pdf, 0, pdf.Length);
}

答案 2 :(得分:2)

如果可以,我建议使用exe - 我认为它更简单。

例如,查看Derp class in another answer of mine有关如何从C#运行wkhtmltopdf exe的信息。或者尝试下面的未经测试的代码(您的真实代码会更复杂,这只是一个演示/ POC)。只需将google.com替换为您想要的HTML页面即可 - 您也可以使用本地文件。

var pi = new ProcessStartInfo(@"c:\wkhtmltopdf\wkhtmltopdf.exe");
pi.CreateNoWindow = true;
pi.UseShellExecute = false;
pi.WorkingDirectory = @"c:\wkhtmltopdf\";
pi.Arguments = "http://www.google.com gogl.pdf";

using (var process = Process.Start(pi))
{
    process.WaitForExit(99999);
    Debug.WriteLine(process.ExitCode);
}

(从https://stackoverflow.com/a/11992062/694325重复回答)

答案 3 :(得分:0)

这会帮助你..........尝试一次。

   protected static byte[] Convert(string wkhtmlPath, string switches, string html, string wkhtmlExe)
    {       
        // generate PDF from given HTML string, not from URL
        if (!string.IsNullOrEmpty(html))
        {               
            html = SpecialCharsEncode(html);
        }

        var proc = new Process();

        var StartInfo = new ProcessStartInfo();

        proc.StartInfo.FileName = Path.Combine(wkhtmlPath, wkhtmlExe);
        proc.StartInfo.Arguments = switches;
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.RedirectStandardOutput = true;
        proc.StartInfo.RedirectStandardError = true;
        proc.StartInfo.RedirectStandardInput = true;
        proc.StartInfo.WorkingDirectory = wkhtmlPath;

        proc.Start();

        // generate PDF from given HTML string, not from URL
        if (!string.IsNullOrEmpty(html))
        {
            using (var sIn = proc.StandardInput)
            {
                sIn.WriteLine(html);
            }
        }

        var ms = new MemoryStream();

        using (var sOut = proc.StandardOutput.BaseStream)
        {                              
            byte[] buffer = new byte[4096];
            int read;

            while ((read = sOut.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
        }

        string error = proc.StandardError.ReadToEnd();

        if (ms.Length == 0)
        {
            throw new Exception(error);
        }

        proc.WaitForExit();

        return ms.ToString(); 
    }


    /// <summary>
    /// Encode all special chars
    /// </summary>
    /// <param name="text">Html text</param>
    /// <returns>Html with special chars encoded</returns>
    private static string SpecialCharsEncode(string text)
    {
        var chars = text.ToCharArray();
        var result = new StringBuilder(text.Length + (int)(text.Length * 0.1));

        foreach (var c in chars)
        {
            var value = System.Convert.ToInt32(c);
            if (value > 127)
                result.AppendFormat("&#{0};", value);
            else
                result.Append(c);
        }

        return result.ToString();
    }


}

这里我们返回内存流,我们还需要添加标题,内容类型

   public override void ExecuteResult(ControllerContext context)
    {
       // this.FileName = context.RouteData.GetRequiredString("action");

        var fileContent =  Convert(wkhtmltopdfPath, switches, null, wkhtmlExe);

        var response = this.PrepareResponse(context.HttpContext.Response);

        response.OutputStream.Write(fileContent, 0, fileContent.Length);
    }

    protected HttpResponseBase PrepareResponse(HttpResponseBase response)
    {
        response.ContentType = this.GetContentType();
        this.FileName = "YourFile.pdf";
        if (!String.IsNullOrEmpty(this.FileName))
        response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", SanitizeFileName(this.FileName)));
        response.AddHeader("Content-Type", this.GetContentType());

        return response;
    }