web-dev-qa-db-fra.com

Comment utiliser wkhtmltopdf.exe dans ASP.net

Après 10 heures et en essayant 4 autres HTML pour PDF outils je suis sur le point d'exploser.

wkhtmltopdf sonne comme une excellente solution ... le problème est que je ne peux pas exécuter un processus avec suffisamment d'autorisations d'asp.net donc ...

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

commence mais ne fait rien.

Existe-t-il un moyen simple:

-a) permettre à asp.net de démarrer des processus (qui peuvent réellement faire quelque chose) ou
- b) compiler/envelopper/tout ce que wkhtmltopdf.exe dans quelque chose que je peux utiliser à partir de C # comme ceci: WkHtmlToPdf.Save("http://www.google.com", "google.pdf");

37
David Murdoch

Vous pouvez également utiliser Pechkin

Wrapper .NET pour DLL WkHtmlToPdf, bibliothèque qui utilise le moteur Webkit pour convertir des pages HTML en PDF.

Forfaits Nuget:

Pechkin.Synchronized

Pechkin

22

Je viens de démarrer un nouveau projet pour fournir un wrapper C # P/Invoke autour de wkhtmltopdf.

Vous pouvez vérifier mon code à: https://github.com/pruiz/WkHtmlToXSharp

Salue.

23
Pablo Ruiz García

Grâce à Paul , j'ai trouvé le bon wrapper écrit par Codaxy, qui peut également être facilement téléchargé via NuGet .

Après quelques essais, j'ai réussi cette action MVC, qui crée et renvoie instantanément le fichier PDF sous forme de flux:

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

Ici, les classes Pdf * ont été implémentées dans le wrapper, avec un code Nice et propre, malheureusement sans documentation.

Dans le convertisseur, l'URL sera convertie en PDF, stockée dans un fichier temporaire, copiée dans le flux que nous avons donné en paramètre, puis le fichier PDF PDF est supprimé.

Enfin, nous devons pousser le flux en tant que FileStreamResult.

N'oubliez pas de mettre la position du flux de sortie à zéro, sinon vous verrez les fichiers PDF téléchargés comme des octets de taille zéro).

15
Bolt Thunder

Voici le code que j'ai utilisé. N'hésitez pas à modifier cela pour vous débarrasser de certaines odeurs et autres terribles ... Je sais que ce n'est pas terrible.

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;
    }
}
4
David Murdoch

Je ne peux pas commenter, donc je poste ceci comme une "réponse" aux commentaires de la réponse ci-dessus Comment utiliser wkhtmltopdf.exe dans ASP.net

Si --redirect-delay ne fonctionne pas, essayez --javascript-delay Voir ici pour toutes les options: https://github.com/antialize/wkhtmltopdf/blob/master/README_WKHTMLTOPDF

Ou faites wkhtmltopdf -H pour une aide étendue (afaik même sortie que le lien ci-dessus).

0
alwin