问题
After 10 hours and trying 4 other HTML to PDF tools I'm about ready to explode.
wkhtmltopdf sounds like an excellent solution...the problem is that I can't execute a process with enough permissions from asp.net so...
Process.Start("wkhtmltopdf.exe","http://www.google.com google.pdf");
starts but doesn't do anything.
Is there an easy way to either:
-a) allow asp.net to start processes (that can actually do something) or
-b) compile/wrap/whatever wkhtmltopdf.exe into somthing I can use from C# like this: WkHtmlToPdf.Save("http://www.google.com", "google.pdf");
回答1:
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
回答2:
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.
回答3:
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.
回答4:
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;
}
}
回答5:
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).
来源:https://stackoverflow.com/questions/2791981/how-to-use-wkhtmltopdf-exe-in-asp-net