在.NET中将HTML转换为PDF

404 html c# pdf itextsharp

我想通过将HTML内容传递给函数来生成PDF.我已经为此使用了iTextSharp,但是当它遇到表格并且布局变得混乱时它表现不佳.

有没有更好的办法?

Mar*_*rko 186

试试wkhtmtopdf.这是迄今为止我发现的最好的工具.

对于.NET,您可以使用此小型库轻松调用wkhtmtopdf命令行实用程序.

  • @bamccaig我已经得到它=)https://github.com/gmanny/Pechkin它公开了库的每个可用功能,并且还有用于多线程的包装器.它在NuGet上. (44认同)
  • 支持.NET ?? (16认同)
  • 在C#中使用它http://stackoverflow.com/questions/4651373/how-to-pass-html-as-a-string-using-wkhtmltopdf/6787041#6787041 (7认同)
  • @AdamMoszczyński:[来自维基百科](http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License):LGPL允许开发人员和公司使用LGPL软件并将其集成到他们自己的(甚至是专有的)软件中而不需要(通过条款)一个强大的copyleft)发布他们自己的软件部分的源代码. (7认同)
  • 它是一个独立的可执行文件.您可以将其作为进程启动,并将HTML文档的URL作为参数传递. (6认同)
  • 我一直在尝试制作.NET绑定(http://github.com/bamccaig/WkHtmlToPdfDflat),但我无法让它工作(我甚至无法直接从C使用C绑定).:\ (5认同)
  • wkhtmtopdf根据[LGPL](http://www.gnu.org/licenses/lgpl.html)获得许可:( (3认同)
  • 它对我有用,并且对阿拉伯语等多语种有很好的支持,唯一的缺点是我需要使用“完全信任”级别,以防使用IIS,这在共享主机或云环境中通常不可行除非您拥有自己的专用服务器,否则作为托管服务提供商进行托管将不会给您“完全信任”级别。 (2认同)
  • WkHtmlToPdf的即用型免费.NET包装器:[NReco.PdfGenerator](http://www.nrecosite.com/pdf_generator_net.aspx).您只需要一个NReco.PdfGenerator.dll,它嵌入所有需要的WkHtmlToPdf文件,并简化使用常见选项(如页面大小,页眉/页脚,边距等). (2认同)
  • 有一个名为TuesPechkin的Pechkin库的更新分支(https://github.com/tuespetre/TuesPechkin).它也可以通过NuGet获得. (2认同)
  • 我在周末做了一些工作,[wkhtmltopdf](http://wkhtmltopdf.org/)是最好的解决方案,.Net包装器是唯一的问题.我发现[NReco](http://www.nrecosite.com/pdf_generator_net.aspx)非常简单可靠,并且有一个NuGet包.这是所有需要的代码`var htmlContent = String.Format("<body> Hello world:{0} </ body>",DateTime.Now); var pdfBytes =(new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(htmlContent);`[Pechkin](https://github.com/gmanny/Pechkin)并不像NReco那样容易. (2认同)

Ane*_*lou 185

编辑: 使用PdfSharp的PDF的新建议HTML渲染器

(在尝试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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

一个很好的替代是一个免费版本iTextSharp的

在版本4.1.6之前,iTextSharp根据LGPL许可证获得许可,版本直到4.16(或者也可能有叉子)作为包提供,可以自由使用.当然有人可以使用续5+ 付费版本.

我试图在我的项目中集成wkhtmltopdf解决方案,并遇到了一些障碍.

我个人会避免在托管企业应用程序上使用基于wkhtmltopdf的解决方案,原因如下.

  1. 首先,wkhtmltopdf是C++实现的而不是C#,您将遇到在C#代码中嵌入它的各种问题,尤其是在项目的32位和64位版本之间切换时.不得不尝试几种解决方法,包括条件项目构建等,以避免在不同的机器上"无效格式异常".
  2. 如果您管理自己的虚拟机,那就可以.但是,如果你的项目就像是一个约束的环境中运行(天青 (实际上是由TuesPenchin笔者提到不可能withing蔚蓝), 弹性魔豆等),它来配置环境只为wkhtmltopdf工作的噩梦.
  3. wkhtmltopdf正在服务器中创建文件,因此您必须管理用户权限并授予对运行wkhtmltopdf的位置的"写入"访问权限.
  4. Wkhtmltopdf作为独立应用程序运行,因此它不受IIS应用程序池的管理.因此,您必须将其作为服务托管在另一台计算机上,否则您将在生产服务器上遇到巨大的处理高峰和内存消耗.
  5. 它使用临时文件生成pdf,而在像AWS EC2这样的情况下,磁盘i/o非常慢,这是一个很大的性能问题.
  6. 许多用户报告的最讨厌的"无法加载DLL'wkhtmltox.dll'"错误.

--- PRE编辑部分---

对于想要在更简单的应用程序/环境中从html生成pdf的任何人,我将旧帖子作为建议.

TuesPechkin

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

或者特别是对于MVC Web应用程序 (但我认为您可以在任何.net应用程序中使用它)

Rotativa

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

他们都利用 wkhtmtopdf二进制文件将html转换为pdf.它使用webkit引擎来呈现页面,因此它也可以解析css样式表.

它们提供易于使用的与C#的无缝集成.

Rotativa还可以从任何Razor View 直接生成PDF .

此外,对于真实的Web应用程序,他们还管理线程安全等...

  • 我们尝试了HtmlRenderer.没有加载任何CSS时它真的很快.但是当我们尝试应用CSS(Bootstrap加上一些定制)时,CSS解析需要一段时间(我们可能会缓解),并且渲染与网页完全不同. (3认同)
  • 感谢您更新帖子.我要试试PdfSharp.你救了我很多时间. (2认同)
  • BS.这将创建HTML的图像并将图像添加到pdf文件中.这根本不是真正的PDF.此外,PDF是一种矢量图形格式 - 您可以无限滚动 - 当然,除非PDF由光栅图形组成,这是该库生成的. (2认同)
  • @Anestis Kivranoglou 我在我的项目中使用了 pdf 锐利。但是对于带有 css 的 html 设计,它无法呈现 html。相反,它只是创建一个空白页面 (2认同)

小智 29

大多数HTML到PDF转换器依赖于IE来进行HTML解析和渲染.当用户更新他们的IE时,这可能会中断.是一个不依赖IE的.

代码是这样的:

EO.Pdf.HtmlToPdf.ConvertHtml(htmlText, pdfFileName);
Run Code Online (Sandbox Code Playgroud)

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

  • d1jhoni1b,这怎么会让它无用?如果它是一种付费工具,那么它可能被认为是昂贵的,但仅凭这一标准并非毫无用处. (46认同)
  • 它没用,因为你必须购买这个库 (35认同)
  • 650美元的单一开发者许可证.这很昂贵. (14认同)
  • 它是免费图书馆吗? (4认同)
  • 这是真的EO.Pdf不使用IE浏览器.但它似乎确实在后台产生了32位webkit浏览器实例.检查您的进程列表,您将看到它们为指向EO.PDF dll的rundll32.exe实例.所以在我看来它仍然有点黑客. (3认同)
  • 它不支持 media="print" 这真的很痛苦。 (2认同)

Mar*_*kus 28

我最近执行了关于HTML到PDF转换的PoC,并希望分享我的结果.

我最喜欢的是OpenHtmlToPdf

该工具的优点:

  • 非常好的HTML兼容性(例如,它是我的示例中唯一一个工具,当一个表跨越多个页面时正确重复的表头)
  • 流畅的API
  • 免费和OpenSource(知识共享署名3.0许可证)
  • 可通过NuGet获得

其他测试工具:


Kim*_*jan 24

我非常推荐NReco.它有免费和付费版本,非常值得.它在后台使用wkhtmtopdf,但你只需要一个程序集.太棒了.

使用示例:

通过NuGet安装.

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

免责声明:我不是开发人员,只是该项目的粉丝:)

  • 看起来确实很有用.值得注意的是,截至今天(05/10/15),它是wkhtmtopdf(作为Nuget包)下载量最大的.Net包装器. (3认同)
  • 尝试过,遗憾的是我无法在azure的网页上使用它. (2认同)

fin*_*s10 24

对于所有在此处及以上寻找可行解决方案的人来说,.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);
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 并将上面的方法调用为HtmlToPdf("test", new string[] { "https://www.google.com" }, new string[] { "-s A5" });
  2. 如果您需要将HTML字符串转换为PDF,请调整上述方法并将toArguments替换为Process StartInfo$@"/C echo | set /p=""{htmlText}"" | ""{pdfHtmlToPdfExePath}"" {((options == null) ? "" : string.Join(" ", options))} - ""C:\Users\xxxx\Desktop\{outputFilename}""";

这种方法的缺点:

  1. 截至发布此答案的最新版本wkhtmltopdf不支持最新版本HTML5CSS3. 因此,如果您尝试导出任何 html,那么CSS GRID输出将不会符合预期。
  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();
Run Code Online (Sandbox Code Playgroud)
  1. html这会将文件转换为pdf文件。
  2. 如果您需要将一些转换urlpdf然后使用以下Argument内容Process 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. 这可以按预期使用最新HTML5功能CSS3。输出将与您在浏览器中查看的内容相同,但是当通过 IIS 运行时,您需要AppliactionPool在 Identity 下运行应用程序LocalSystem,或者您需要提供read/write访问IISUSRS.

使用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;
}
Run Code Online (Sandbox Code Playgroud)

这种方法的优点:

  1. 这只需要安装 Nuget 即可按预期使用最新HTML5功能CSS3。输出将与您在浏览器中查看的内容相同。

这种方法的缺点:

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

如果我们在 docker 中运行应用程序,上述缺点就可以克服。我们需要做的就是在构建应用程序映像时安装 chromeDockerfile

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

<PropertyGroup>
  <TargetFramework>net5.0</TargetFramework>
  <LangVersion>latest</LangVersion>
  <Nullable>enable</Nullable>
  <PublishChromeDriver>true</PublishChromeDriver>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

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

这是我的工作项目存储库的链接 - HtmlToPdf

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

如果用户通过浏览器使用您的应用程序,那么您可以依赖JavaScript并使用window.print()必要的内容print media css从浏览器生成 PDF。例如,从库存应用程序中的浏览器生成发票。

这种方法的优点:

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

这种方法的缺点:

  1. 例如,我们需要做一些解决方法来打印页面的各个部分SPABlazoriframe

我花了几乎 2 天的时间研究可用选项并最终实施了Selenium基于解决方案并且它正在工作,之后我得出了上述答案。希望这对您有帮助并节省您的时间。


Ste*_*art 13

Winnovative提供支持HTML输入的.Net PDF库.他们提供无限制的免费试用.根据您希望部署项目的方式,这可能就足够了.

  • 请记住,当我们上次检查时,winnovative与IE9不兼容(因为它们使用IE9中删除的IE GDI渲染引擎).因此,如果您在使用它的计算机上安装了IE9,则转换将无效.他们可能已经解决了这个问题,但是很多商业组件都使用了IE渲染引擎,并且在IE9中出现了问题,所以值得一试. (4认同)

Leo*_* AB 10

您可以在无头模式下使用 Google Chrome 打印到 pdf 功能。我发现这是最简单但最强大的方法。

var url = "/sf/ask/39525531/";
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();
    }

Run Code Online (Sandbox Code Playgroud)

  • 为了让IIS中的ASP.NET能够以写访问权限运行外部程序,应用程序池&gt;高级设置&gt;身份&gt;设置为“LocalSystem” (2认同)

小智 8

基本PDF可用于将HTML转换为PDF:C#sample.链接到此处的示例是基于ASP.NET的,但可以从Windows窗体,WPF,ASP.NET Webforms和ASP.NET MVC使用该库.该库提供了使用不同HTML呈现引擎的选项:Internet Explorer(默认)和WebKit(最佳输出).

如果您符合条件,则可通过社区许可计划免费获得整套控件(商业应用程序).社区许可证是完整的产品,没有任何限制或水印.

注意:我为Syncfusion工作.


Ale*_*sco 8

大多数项目很可能会包装 C/C++ 引擎,而不是从头开始实现 C# 解决方案。试试哥登堡计划。

测试一下

docker run --rm -p 3000:3000 thecodingmachine/gotenberg:6
Run Code Online (Sandbox Code Playgroud)

卷曲样品

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
Run Code Online (Sandbox Code Playgroud)

C# 示例.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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编译

csc sample.cs -langversion:latest -reference:System.Net.Http.dll && mono ./sample.exe
Run Code Online (Sandbox Code Playgroud)


小智 7

我使用了ExpertPDF Html To Pdf Converter.做得体.不幸的是,这不是免费的.


小智 7

还有一个新的基于Web的文档生成应用程序 - DocRaptor.com.看似易于使用,并且有免费选项.


Pet*_*uss 7

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

有关HTML-to-PDF要求的好消息.正如这个答案所示,W3C标准css-break-3将解决这个问题 ......这是一个候选推荐标准,计划在经过测试后于2017年或2018年转为最终推荐标准.

由于没有那么标准,因此有一些解决方案,带有C#插件,如print-css.rocks所示.

  • print-css.rocks 链接的解决方案的 PDFreactor 售价为 2,950.00 美元,Prince 售价为 3800 美元,Antenna House Formatter V7 售价为 5,000.00 美元。Weasyprint 似乎适用于 Python。 (2认同)

Abh*_*pta 7

这是一个免费的库,工作起来非常容易:OpenHtmlToPdf

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
Run Code Online (Sandbox Code Playgroud)


Ste*_*art 6

如果您真的不需要真正的.Net PDF库,那么有许多免费的HTML到PDF工具,其中许多可以从命令行运行.

一种解决方案是选择其中一种,然后在C#中编写一个薄包装器.例如,正如本教程中所做的那样.


Mau*_*rez 6

上次更新时间:2019年9月

这是我汇总的.NET中HTML到PDF转换的选项列表(有些是免费的,有些是付费的)

如果以上选项均无济于事,您可以随时搜索NuGet软件包 https://www.nuget.org/packages?q=html+pdf

  • 你测试过性能吗?我们正在寻求改善当前的转换时间,并正在探索其他库以获得这些性能优势 (3认同)
  • DinkToPdf 是免费的并且在 .net core 中工作。https://www.nuget.org/packages/DinkToPdf/ (3认同)
  • 另一个基于 wkhtmtopdf 的解决方案甚至可以在 Azure Web 服务上工作,它是 DinkToPdf 分支:https://github.com/hakanl/DinkToPdf 和 nuget:https://www.nuget.org/packages/Haukcode.DinkToPdf (2认同)
  • @FritsJ 列表中有很多选项;-) (2认同)
  • 更新这个清单!!另外,请检查此解决方案:https://github.com/eKoopmans/html2pdf.js#getting-started 它让我陷入了困境,直到 .dotnet 6 打破了它,我不得不重新开始。 (2认同)

Run*_*tad 3

这取决于您的任何其他要求。

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

编辑:如果您的 Html 是 XHtml,您可以使用PDFizer来完成这项工作。