How to use wkhtmltopdf.exe in ASP.net [duplicate]

Deadly 提交于 2019-11-27 17:23:54

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

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.

Bolt Thunder

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.

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;
    }
}
alwin

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).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!