在.NET中将HTML转换为PDF

我想通过将HTML内容传递给函数来生成PDF。我已经为此使用了iTextSharp,但它在遇到表和布局时表现不佳。

有没有更好的办法?

810633 次浏览

这取决于您的其他需求。

一个非常简单但不容易部署的解决方案是使用WebBrowser控件加载Html,然后使用Print方法打印到本地安装的PDF打印机。有一些免费的PDF打印机,WebBrowser控件是. net框架的一部分。

< p >编辑: 如果你的Html是XHtml,你可以使用PDFizer来完成这项工作

我之前也在找这个。我遇到了HTMLDOC http://www.easysw.com/htmldoc/,这是一个免费的开源命令行应用程序,它以HTML文件为参数,并从中吐出PDF文件。这在我的副业项目中非常有效,但这完全取决于你真正需要什么。

制作它的公司出售编译后的二进制文件,但您可以免费从源代码下载和编译并使用它。我设法编译了一个最近的版本(1.9版本),我打算在几天内发布它的二进制安装程序,所以如果你感兴趣,我可以在发布它时立即提供它的链接。

编辑(2/25/2014):似乎文档和网站移动到http://www.msweet.org/projects.php?Z1

试试这个PDF Duo .Net转换组件,在不使用额外dll的情况下转换HTML到PDF从ASP。网应用程序。

您可以传递HTML字符串或文件,或流来生成PDF。 使用下面的代码(示例c#):

string file_html = @"K:\hdoc.html";
string file_pdf = @"K:\new.pdf";
try
{
DuoDimension.HtmlToPdf conv = new DuoDimension.HtmlToPdf();
conv.OpenHTML(file_html);
conv.SavePDF(file_pdf);
textBox4.Text = "C# Example: Converting succeeded";
}

Info + c# /VB示例可以在:http://www.duodimension.com/html_pdf_asp.net/component_html_pdf.aspx找到

在c#中转换HTML到PDF使用ABCpdf

ABCpdf可以使用Gecko或Trident呈现引擎,因此您的HTML表看起来与FireFox和Internet Explorer中的相同。

在www.abcpdfeditor.com上有一个ABCpdf的在线演示。您可以使用它来检查您的表将如何首先呈现,而不需要下载和安装软件。

为了渲染整个网页,你需要AddImageUrl或AddImageHtml函数。但如果你想做的只是添加HTML样式的文本,那么你可以尝试AddHtml函数,如下所示:

Doc theDoc = new Doc();
theDoc.FontSize = 72;
theDoc.AddHtml("<b>Some HTML styled text</b>");
theDoc.Save(Server.MapPath("docaddhtml.pdf"));
theDoc.Clear();

ABCpdf是一个商业软件,但是标准版通常可以在特别优惠下免费获得。

HTML到PDF的转换大多依赖于IE来完成HTML的解析和渲染。这可以打破用户更新他们的IE。在这里是一个不依赖IE的函数。

代码是这样的:

EO.Pdf.HtmlToPdf.ConvertHtml(htmlText, pdfFileName);

像许多其他转换器一样,您可以传递文本、文件名或Url。结果可以保存到文件或流中。

不是直接将HTML解析为PDF,而是可以创建HTML页面的位图,然后将位图插入到PDF中,例如使用iTextSharp

这是一个代码如何获得一个URL的位图。我在这里找到了它,如果我找到了源,我会链接它。

public System.Drawing.Bitmap HTMLToImage(String strHTML)
{
System.Drawing.Bitmap myBitmap = null;


System.Threading.Thread myThread = new System.Threading.Thread(delegate()
{
// create a hidden web browser, which will navigate to the page
System.Windows.Forms.WebBrowser myWebBrowser = new System.Windows.Forms.WebBrowser();
// we don't want scrollbars on our image
myWebBrowser.ScrollBarsEnabled = false;
// don't let any errors shine through
myWebBrowser.ScriptErrorsSuppressed = true;
// let's load up that page!
myWebBrowser.Navigate("about:blank");


// wait until the page is fully loaded
while (myWebBrowser.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
System.Windows.Forms.Application.DoEvents();


myWebBrowser.Document.Body.InnerHtml = strHTML;


// set the size of our web browser to be the same size as the page
int intScrollPadding = 20;
int intDocumentWidth = myWebBrowser.Document.Body.ScrollRectangle.Width + intScrollPadding;
int intDocumentHeight = myWebBrowser.Document.Body.ScrollRectangle.Height + intScrollPadding;
myWebBrowser.Width = intDocumentWidth;
myWebBrowser.Height = intDocumentHeight;
// a bitmap that we will draw to
myBitmap = new System.Drawing.Bitmap(intDocumentWidth - intScrollPadding, intDocumentHeight - intScrollPadding);
// draw the web browser to the bitmap
myWebBrowser.DrawToBitmap(myBitmap, new System.Drawing.Rectangle(0, 0, intDocumentWidth - intScrollPadding, intDocumentHeight - intScrollPadding));
});
myThread.SetApartmentState(System.Threading.ApartmentState.STA);
myThread.Start();
myThread.Join();


return myBitmap;
}

使用Winnovative HTML到PDF转换器,您可以在单行中转换HTML字符串

byte[] outPdfBuffer = htmlToPdfConverter.ConvertHtml(htmlString, baseUrl);

基URL用于解析HTML字符串中相对URL引用的图像。另外,你也可以在HTML中使用完整的url,或者使用src="data:image/png"作为图像标签嵌入图像。

在回答'fubaar'用户对Winnovative转换器的评论时,有必要进行更正。转换器不使用IE作为渲染引擎。它实际上不依赖于任何安装的软件,并且渲染与WebKit引擎兼容。

如果你需要完美的html pdf渲染,你需要使用商业库。

ExpertPdf Html到Pdf转换器非常容易使用,它支持最新的html5/css3。您可以将整个url转换为pdf:

using ExpertPdf.HtmlToPdf;
byte[] pdfBytes = new PdfConverter().GetPdfBytesFromUrl(url);

或者HTML字符串:

using ExpertPdf.HtmlToPdf;
byte[] pdfBytes = new PdfConverter().GetPdfBytesFromHtmlString(html, baseUrl);

您还可以选择直接将生成的pdf文档保存到磁盘上的文件流。

如果你想让用户在浏览器中下载渲染页面的pdf,那么最简单的解决方案是

window.print();

在客户端,它将提示用户保存当前页面的PDF。您还可以通过链接样式自定义pdf的外观

<link rel="stylesheet" type="text/css" href="print.css" media="print">

css在打印时应用于HTML。

限制

您不能将文件存储在服务器端。 用户提示打印页面时,必须手动保存页面。

.

.

最好的工具,我发现和用于生成javascript和样式渲染视图或html页面的PDF是phantomJS

下载带有rasterize.js函数的.exe文件,在示例文件夹的exe根目录下找到,并放入解决方案。

它甚至允许你下载文件在任何代码,而不打开该文件,它也允许下载文件时,风格和特别是jquery应用。

以下代码生成PDF文件:

public ActionResult DownloadHighChartHtml()
{
string serverPath = Server.MapPath("~/phantomjs/");
string filename = DateTime.Now.ToString("ddMMyyyy_hhmmss") + ".pdf";
string Url = "http://wwwabc.com";


new Thread(new ParameterizedThreadStart(x =>
{
ExecuteCommand(string.Format("cd {0} & E: & phantomjs rasterize.js {1} {2} \"A4\"", serverPath, Url, filename));
//E: is the drive for server.mappath
})).Start();


var filePath = Path.Combine(Server.MapPath("~/phantomjs/"), filename);


var stream = new MemoryStream();
byte[] bytes = DoWhile(filePath);


Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=Image.pdf");
Response.OutputStream.Write(bytes, 0, bytes.Length);
Response.End();
return RedirectToAction("HighChart");
}






private void ExecuteCommand(string Command)
{
try
{
ProcessStartInfo ProcessInfo;
Process Process;


ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + Command);


ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = false;


Process = Process.Start(ProcessInfo);
}
catch { }
}




private byte[] DoWhile(string filePath)
{
byte[] bytes = new byte[0];
bool fail = true;


while (fail)
{
try
{
using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
}


fail = false;
}
catch
{
Thread.Sleep(1000);
}
}


System.IO.File.Delete(filePath);
return bytes;
}

我强烈推荐NReco,真的。它有免费版和付费版,真的很值得。它在后台使用wkhtmtopdf,但只需要一个程序集。太棒了。

使用示例:

通过NuGet安装。

var htmlContent = String.Format("<body>Hello world: {0}</body>", DateTime.Now);
var pdfBytes = (new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(htmlContent);

免责声明:我不是开发者,只是这个项目的粉丝:)

EDIT:新建议 使用PdfSharp的PDF HTML渲染器 < / p >

(在尝试wkhtmltopdf并建议避免它之后)

HtmlRenderer。PdfSharp是一个100%全c#管理代码容易使用,线程安全,最重要的是免费的 (新的BSD许可证)解决方案。

使用

  1. 下载HtmlRenderer。PdfSharp nuget包。
  2. 使用示例方法。

    public static Byte[] PdfSharpConvert(String html)
    {
    Byte[] res = null;
    using (MemoryStream ms = new MemoryStream())
    {
    var pdf = TheArtOfDev.HtmlRenderer.PdfSharp.PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
    pdf.Save(ms);
    res = ms.ToArray();
    }
    return res;
    }
    

A very Good Alternate Is a Free Version of iTextSharp

Until version 4.1.6 iTextSharp was licensed under the LGPL licence and versions until 4.16 (or there may be also forks) are available as packages and can be freely used. Of course someone can use the continued 5+ paid version.

I tried to integrate wkhtmltopdf solutions on my project and had a bunch of hurdles.

I personally would avoid using wkhtmltopdf - based solutions on Hosted Enterprise applications for the following reasons.

  1. First of all wkhtmltopdf is C++ implemented not C#, and you will experience various problems embedding it within your C# code, especially while switching between 32bit and 64bit builds of your project. Had to try several workarounds including conditional project building etc. etc. just to avoid "invalid format exceptions" on different machines.
  2. If you manage your own virtual machine its ok. But if your project is running within a constrained environment like (Azure (Actually is impossible withing azure as mentioned by the TuesPenchin author) , Elastic Beanstalk etc) it's a nightmare to configure that environment only for wkhtmltopdf to work.
  3. wkhtmltopdf is creating files within your server so you have to manage user permissions and grant "write" access to where wkhtmltopdf is running.
  4. Wkhtmltopdf is running as a standalone application, so its not managed by your IIS application pool. So you have to either host it as a service on another machine or you will experience processing spikes and memory consumption within your production server.
  5. It uses temp files to generate the pdf, and in cases Like AWS EC2 which has really slow disk i/o it is a big performance problem.
  6. The most hated "Unable to load DLL 'wkhtmltox.dll'" error reported by many users.

--- PRE Edit Section ---

For anyone who want to generate pdf from html in simpler applications / environments I leave my old post as suggestion.

TuesPechkin

https://www.nuget.org/packages/TuesPechkin/

or Especially For MVC Web Applications (But I think you may use it in any .net application)

Rotativa

https://www.nuget.org/packages/Rotativa/

They both utilize the wkhtmtopdf binary for converting html to pdf. Which uses the webkit engine for rendering the pages so it can also parse css style sheets.

They provide easy to use seamless integration with C#.

Rotativa can also generate directly PDFs from any Razor View.

Additionally for real world web applications they also manage thread safety etc...

你也可以检查尖塔,它允许你用这段简单的代码创建HTML to PDF

 string htmlCode = "<p>This is a p tag</p>";
 

//use single thread to generate the pdf from above html code
Thread thread = new Thread(() =>
{ pdf.LoadFromHTML(htmlCode, false, setting, htmlLayoutFormat); });
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
 

// Save the file to PDF and preview it.
pdf.SaveToFile("output.pdf");
System.Diagnostics.Process.Start("output.pdf");

PDFmyURL最近也发布了一个。net组件,用于网页/ HTML到PDF的转换。它有一个非常友好的用户界面,例如:

PDFmyURL pdf = new PDFmyURL("yourlicensekey");
pdf.ConvertURL("http://www.example.com", Application.StartupPath + @"\example.pdf");

文档:PDFmyURL .NET组件文档

免责声明:我为拥有PDFmyURL的公司工作

如果你已经在使用itextsharp dll,不需要添加第三方dll's(插件),我认为你正在使用htmlworker而不是它使用xmlworker,你可以很容易地将你的html转换为pdf 一些css不能工作,它们是支持CSS
完整的解释与示例参考点击这里 < / p >

< br >

        MemoryStream memStream = new MemoryStream();
TextReader xmlString = new StringReader(outXml);
using (Document document = new Document())
{
PdfWriter writer = PdfWriter.GetInstance(document, memStream);
//document.SetPageSize(iTextSharp.text.PageSize.A4);
document.Open();
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(outXml);
MemoryStream ms = new MemoryStream(byteArray);
XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, ms, System.Text.Encoding.UTF8);
document.Close();
}


Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=" + filename + ".pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.BinaryWrite(memStream.ToArray());
Response.End();
Response.Flush();

下面是一个使用iTextSharp将html + css转换为PDF的示例(iTextSharp + iTextSharp .xmlworker)

using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.tool.xml;




byte[] pdf; // result will be here


var cssText = File.ReadAllText(MapPath("~/css/test.css"));
var html = File.ReadAllText(MapPath("~/css/test.html"));


using (var memoryStream = new MemoryStream())
{
var document = new Document(PageSize.A4, 50, 50, 60, 60);
var writer = PdfWriter.GetInstance(document, memoryStream);
document.Open();


using (var cssMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(cssText)))
{
using (var htmlMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(html)))
{
XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, htmlMemoryStream, cssMemoryStream);
}
}


document.Close();


pdf = memoryStream.ToArray();
}

作为HiQPdf软件的代表,我认为最好的解决方案是HiQPdf HTML到。net的PDF转换器。它包含了市场上最先进的HTML5, CSS3, SVG和JavaScript渲染引擎。还有一个免费版本的HTML到PDF库,你可以使用它来免费生成最多3个PDF页面。从HTML页面生成以字节[]为单位的PDF的最小c#代码是:

HtmlToPdf htmlToPdfConverter = new HtmlToPdf();


// set PDF page size, orientation and margins
htmlToPdfConverter.Document.PageSize = PdfPageSize.A4;
htmlToPdfConverter.Document.PageOrientation = PdfPageOrientation.Portrait;
htmlToPdfConverter.Document.Margins = new PdfMargins(0);


// convert HTML to PDF
byte[] pdfBuffer = htmlToPdfConverter.ConvertUrlToMemory(url);

你可以找到更详细的例子。NET和MVC在HiQPdf HTML到PDF转换器示例库

另一个建议是尝试https://grabz.it的解决方案。

他们提供了一个很好的。net API来捕捉屏幕截图,并以一种简单灵活的方式进行操作。

要在你的应用程序中使用它,你需要首先获得密钥+秘密下载的。net SDK(它是免费的)。

下面是一个简短的例子。

要使用这个API,你首先需要创建一个GrabzItClient类的实例,将你的应用密钥和应用秘密从你的GrabzIt账户传递给构造函数,如下面的例子所示:

//Create the GrabzItClient class
//Replace "APPLICATION KEY", "APPLICATION SECRET" with the values from your account!
private GrabzItClient grabzIt = GrabzItClient.Create("Sign in to view your Application Key", "Sign in to view your Application Secret");

现在,要将HTML转换为PDF,你需要做的是:

grabzIt.HTMLToPDF("<html><body><h1>Hello World!</h1></body></html>");

你也可以转换为图像:

grabzIt.HTMLToImage("<html><body><h1>Hello World!</h1></body></html>");

接下来需要保存图像。可以使用两个可用的保存方法之一,如果可用公共可访问的回调句柄,则使用Save,否则使用SaveTo检查文档获取详细信息。

2018年的更新,让我们使用标准的HTML+CSS=PDF方程式!

对于html到pdf的需求,有一个好消息。As 这个答案显示W3C标准css-break-3将解决这个问题…这是一份候选人推荐书,计划在2017年或2018年经过测试后成为正式推荐书。

作为不那么标准的解决方案,有c#的插件,如print-css.rocks所示。

这是一个免费图书馆,非常容易工作:< em > OpenHtmlToPdf < / em >

string timeStampForPdfName = DateTime.Now.ToString("yyMMddHHmmssff");


string serverPath = System.Web.Hosting.HostingEnvironment.MapPath("~/FolderName");
string pdfSavePath = Path.Combine(@serverPath, "FileName" + timeStampForPdfName + ".FileExtension");




//OpenHtmlToPdf Library used for Performing PDF Conversion
var pdf = Pdf.From(HTML_String).Content();


//FOr writing to file from a ByteArray
File.WriteAllBytes(pdfSavePath, pdf.ToArray()); // Requires System.Linq

你可以使用WebBrowser控件的另一个技巧,下面是我的完整工作代码

在我的例子中,为文本框控件分配Url

  protected void Page_Load(object sender, EventArgs e)
{


txtweburl.Text = "https://www.google.com/";


}

下面是使用线程生成屏幕的代码

  protected void btnscreenshot_click(object sender, EventArgs e)
{
//  btnscreenshot.Visible = false;
allpanels.Visible = true;
Thread thread = new Thread(GenerateThumbnail);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();


}


private void GenerateThumbnail()
{
//  btnscreenshot.Visible = false;
WebBrowser webrowse = new WebBrowser();
webrowse.ScrollBarsEnabled = false;
webrowse.AllowNavigation = true;
string url = txtweburl.Text.Trim();
webrowse.Navigate(url);
webrowse.Width = 1400;
webrowse.Height = 50000;


webrowse.DocumentCompleted += webbrowse_DocumentCompleted;
while (webrowse.ReadyState != WebBrowserReadyState.Complete)
{
System.Windows.Forms.Application.DoEvents();
}
}

在下面的代码中,我下载后保存pdf文件

        private void webbrowse_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// btnscreenshot.Visible = false;
string folderPath = Server.MapPath("~/ImageFiles/");


WebBrowser webrowse = sender as WebBrowser;
//Bitmap bitmap = new Bitmap(webrowse.Width, webrowse.Height);


Bitmap bitmap = new Bitmap(webrowse.Width, webrowse.Height, PixelFormat.Format16bppRgb565);


webrowse.DrawToBitmap(bitmap, webrowse.Bounds);




string Systemimagedownloadpath = System.Configuration.ConfigurationManager.AppSettings["Systemimagedownloadpath"].ToString();
string fullOutputPath = Systemimagedownloadpath + Request.QueryString["VisitedId"].ToString() + ".png";
MemoryStream stream = new MemoryStream();
bitmap.Save(fullOutputPath, System.Drawing.Imaging.ImageFormat.Jpeg);






//generating pdf code
Document pdfDoc = new Document(new iTextSharp.text.Rectangle(1100f, 20000.25f));
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
pdfDoc.Open();
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(fullOutputPath);
img.ScaleAbsoluteHeight(20000);
img.ScaleAbsoluteWidth(1024);
pdfDoc.Add(img);
pdfDoc.Close();
//Download the PDF file.
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=ImageExport.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Write(pdfDoc);
Response.End();




}

你也可以参考我最老的帖子获得更多信息:到网页的导航被取消,以asp.net web形式获取消息

最后更新:2020年10月

这是我整理的。net中HTML到PDF转换的选项列表(有些是免费的,有些是付费的)

如果上面的选项都没有帮助你,你可以总是搜索NuGet包 https://www.nuget.org/packages?q=html+pdf < / p >

到目前为止,似乎最好的免费的 . net解决方案是TuesPechkin库,它是wkhtmltopdf本机库的包装器。

我现在已经使用单线程版本将几千个HTML字符串转换为PDF文件,它似乎工作得很好。它应该也可以在多线程环境中工作(例如IIS),但我还没有对此进行测试。

另外,由于我想使用wkhtmltopdf的最新版本(在撰写本文时为0.12.5),我从官方网站下载了DLL,将其复制到我的项目根目录,将copy to output设置为true,并像这样初始化库:

var dllDir = AppDomain.CurrentDomain.BaseDirectory;
Converter = new StandardConverter(new PdfToolset(new StaticDeployment(dllDir)));

上面的代码看起来会是< em >是< / em > " wkhtmlox .dll",所以不要重命名文件。我使用的是64位版本的DLL。

确保你阅读了多线程环境的说明,因为你只需要在每个应用生命周期中初始化它一次,所以你需要把它放在一个单例或其他东西中。

你可以使用谷歌Chrome打印到pdf功能从它的无头模式。我发现这是最简单但最健壮的方法。

var url = "https://stackoverflow.com/questions/564650/convert-html-to-pdf-in-net";
var chromePath = @"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe";
var output = Path.Combine(Environment.CurrentDirectory, "printout.pdf");
using (var p = new Process())
{
p.StartInfo.FileName = chromePath;
p.StartInfo.Arguments = $"--headless --disable-gpu --print-to-pdf={output} {url}";
p.Start();
p.WaitForExit();
}


很可能大多数项目将包装C/ c++引擎,而不是从头开始实现c#解决方案。试试项目Gotenberg

为了测试它

docker run --rm -p 3000:3000 thecodingmachine/gotenberg:6

旋度样本

curl --request POST \
--url http://localhost:3000/convert/url \
--header 'Content-Type: multipart/form-data' \
--form remoteURL=https://brave.com \
--form marginTop=0 \
--form marginBottom=0 \
--form marginLeft=0 \
--form marginRight=0 \
-o result.pdf

c# sample.cs

using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
using static System.Console;


namespace Gotenberg
{
class Program
{
public static async Task Main(string[] args)
{
try
{
var client = new HttpClient();
var formContent = new MultipartFormDataContent
{
{new StringContent("https://brave.com/"), "remoteURL"},
{new StringContent("0"), "marginTop" }
};
var result = await client.PostAsync(new Uri("http://localhost:3000/convert/url"), formContent);
await File.WriteAllBytesAsync("brave.com.pdf", await result.Content.ReadAsByteArrayAsync());
}
catch (Exception ex)
{
WriteLine(ex);
}
}
}
}

要编译

csc sample.cs -langversion:latest -reference:System.Net.Http.dll && mono ./sample.exe

对于所有那些在.net 5和以上寻找工作解决方案的人来说,你去吧。

以下是我的工作解决方案。

使用wkhtmltopdf:

  1. 在这里下载并安装wkhtmltopdf最新版本。
  2. 使用下面的代码。
public static string HtmlToPdf(string outputFilenamePrefix, string[] urls,
string[] options = null,
string pdfHtmlToPdfExePath = @"C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe")
{
string urlsSeparatedBySpaces = string.Empty;
try
{
//Determine inputs
if ((urls == null) || (urls.Length == 0))
throw new Exception("No input URLs provided for HtmlToPdf");
else
urlsSeparatedBySpaces = String.Join(" ", urls); //Concatenate URLs


string outputFilename = outputFilenamePrefix + "_" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss-fff") + ".PDF"; // assemble destination PDF file name


var p = new System.Diagnostics.Process()
{
StartInfo =
{
FileName = pdfHtmlToPdfExePath,
Arguments = ((options == null) ? "" : string.Join(" ", options)) + " " + urlsSeparatedBySpaces + " " + outputFilename,
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 = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location))
}
};


p.Start();


// read the output here...
var output = p.StandardOutput.ReadToEnd();
var errorOutput = p.StandardError.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 so return path of pdf
if ((returnCode == 0) || (returnCode == 2))
return outputFilename;
else
throw new Exception(errorOutput);
}
catch (Exception exc)
{
throw new Exception("Problem generating PDF from HTML, URLs: " + urlsSeparatedBySpaces + ", outputFilename: " + outputFilenamePrefix, exc);
}
}
  1. 并调用上面的方法HtmlToPdf("test", new string[] { "https://www.google.com" }, new string[] { "-s A5" });
  2. 如果你需要将HTML字符串转换为PDF,调整上述方法并将Arguments替换为$@"/C echo | set /p=""{htmlText}"" | ""{pdfHtmlToPdfExePath}"" {((options == null) ? "" : string.Join(" ", options))} - ""C:\Users\xxxx\Desktop\{outputFilename}""";

这种方法的缺点:

  1. 在发布此答案时,wkhtmltopdf的最新版本不支持最新的HTML5CSS3。因此,如果你试图导出任何作为CSS GRID的html,那么输出将不会像预期的那样。
  2. 您需要处理并发性问题。

使用chrome headless:

  1. 在这里下载并安装最新的chrome浏览器。
  2. 使用下面的代码。
var p = new System.Diagnostics.Process()
{
StartInfo =
{
FileName = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe",
Arguments = @"/C --headless --disable-gpu --run-all-compositor-stages-before-draw --print-to-pdf-no-header --print-to-pdf=""C:/Users/Abdul Rahman/Desktop/test.pdf"" ""C:/Users/Abdul Rahman/Desktop/grid.html""",
}
};


p.Start();


// ...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();
  1. 这将把html文件转换为pdf文件。
  2. 如果你需要将一些url转换为pdf,那么使用下面的ArgumentProcess StartInfo

@"/C --headless --disable-gpu --run-all-compositor-stages-before-draw --print-to-pdf-no-header --print-to-pdf=""C:/Users/Abdul Rahman/Desktop/test.pdf"" ""https://www.google.com""",

这种方法的缺点:

  1. 这与最新的HTML5CSS3特性的预期工作一样。输出将与你在浏览器中看到的相同,但当通过IIS运行时,你需要在LocalSystem身份下运行应用程序的AppliactionPool,或者你需要为IISUSRS提供read/write访问。

使用Selenium WebDriver:

  1. 安装Nuget包Selenium.WebDriverSelenium.WebDriver.ChromeDriver
  2. 使用下面的代码。
public async Task<byte[]> ConvertHtmlToPdf(string html)
{
var directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments), "ApplicationName");
Directory.CreateDirectory(directory);
var filePath = Path.Combine(directory, $"{Guid.NewGuid()}.html");
await File.WriteAllTextAsync(filePath, html);


var driverOptions = new ChromeOptions();
// In headless mode, PDF writing is enabled by default (tested with driver major version 85)
driverOptions.AddArgument("headless");
using var driver = new ChromeDriver(driverOptions);
driver.Navigate().GoToUrl(filePath);


// Output a PDF of the first page in A4 size at 90% scale
var printOptions = new Dictionary<string, object>
{
{ "paperWidth", 210 / 25.4 },
{ "paperHeight", 297 / 25.4 },
{ "scale", 0.9 },
{ "pageRanges", "1" }
};
var printOutput = driver.ExecuteChromeCommandWithResult("Page.printToPDF", printOptions) as Dictionary<string, object>;
var pdf = Convert.FromBase64String(printOutput["data"] as string);


File.Delete(filePath);


return pdf;
}

该方法的优点:

  1. 这只需要安装一个Nuget,并使用最新的HTML5CSS3功能正常工作。输出将与您在浏览器中查看的相同。

这种方法的缺点:

  1. 这种方法需要在应用程序运行的服务器上安装最新的chrome浏览器。
  2. 如果服务器中的chrome浏览器版本更新,则Selenium.WebDriver.ChromeDriver Nuget包需要更新。否则,由于版本不匹配,将抛出运行时错误。

使用这种方法,请确保在.csproj文件中添加<PublishChromeDriver>true</PublishChromeDriver>,如下所示:

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<PublishChromeDriver>true</PublishChromeDriver>
</PropertyGroup>

这将在发布项目时发布chrome driver

这是我的工作项目repo - HtmlToPdf的链接

JavaScript中使用window.print()从浏览器生成PDF

如果用户是从浏览器使用你的应用程序,那么你可以依赖JavaScript并使用window.print()和必要的print media css从浏览器生成PDF。例如,生成发票从浏览器在一个库存应用程序。

该方法的优点:

  1. 不依赖于任何工具。
  2. 在浏览器中直接从HTML, CSS和JS生成PDF。
  3. 支持所有最新的CSS属性。

这种方法的缺点:

  1. 在像Blazor这样的SPA中,我们需要使用iframe来打印页面的各个部分。

在几乎花了2天的时间与可用的选项后,我得到了上面的答案,最终实现了基于Selenium的解决方案,它正在工作。希望这能帮到你,节省你的时间。