使用 IText 7 从 html 转换生成一个包含多个页面的 pdf 文档

Generate one pdf document with multiple pages converting from html using IText 7

我正在使用 IText 7,我已经能够获得一个 html 页面并为该页面生成一个 pdf,但我需要从多个 html 页并以页分隔。例如:我有 Page1.htmlPage2.htmlPage3.html。我需要一个 3 页的 pdf 文档,第一页的内容为 Page1.html,第二页的内容为 Page2.html 等等...

这是我的代码,它适用于一个 html 页面:

ConverterProperties properties = new ConverterProperties();              
PdfWriter writer = new PdfWriter(pdfRoot, new WriterProperties().SetFullCompressionMode(true));
PdfDocument pdfDocument = new PdfDocument(writer);
pdfDocument.AddEventHandler(PdfDocumentEvent.END_PAGE, new HeaderPdfEventHandler());
HtmlConverter.ConvertToPdf(htmlContent, pdfDocument, properties);

是否可以针对多个 html 页面进行循环,为每个 html 页面向 PdfDocument 添加一个新页面,然后每个 html 仅生成一个页面一页的 pdf ] 页?

更新

我一直在关注 this 示例并尝试将其从 Java 转换为 C#,我正在尝试使用 PdfMerger 并围绕 html页面...但我在这一行收到异常 Cannot access a closed stream

temp = new PdfDocument(
                    new PdfReader(new RandomAccessSourceFactory().CreateSource(baos), rp));

看起来与 ByteArrayOutputStream baos 实例有关。有什么建议么?这是我当前的代码:

foreach (var html in htmlList)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfDocument temp = new PdfDocument(new PdfWriter(baos));
    HtmlConverter.ConvertToPdf(html, temp, properties);              
    ReaderProperties rp = new ReaderProperties();
    temp = new PdfDocument(
        new PdfReader(new RandomAccessSourceFactory().CreateSource(baos), rp));
    merger.Merge(temp, 1, temp.GetNumberOfPages());
    temp.Close();
}
pdfDocument.Close();

您正在使用 RandomAccessSourceFactory 并向其中传递一个您写入 PDF 文档的封闭流。 RandomAccessSourceFactory 需要一个准备好读取的输入流。

首先,您应该使用 .NET 世界原生的 MemoryStreamByteArrayOutputStream 是出于内部目的从 Java 移植而来的 class(尽管它也扩展了 MemoryStream)。其次,您不必使用 RandomAccessSourceFactory - 有一种更简单的方法。

您可以使用以下行从用于创建临时 PDF 的 MemoryStream 的字节创建一个新的 MemoryStream 实例:

baos = new MemoryStream(baos.ToArray());

作为附加说明,最好直接关闭 PdfMerger 实例而不是关闭文档 - 关闭 PdfMerger 也会关闭基础文档。

总而言之,我们得到了以下有效的代码:

foreach (var html in htmlList)
{
    MemoryStream baos = new MemoryStream();
    PdfDocument temp = new PdfDocument(new PdfWriter(baos));
    HtmlConverter.ConvertToPdf(html, temp, properties);              
    ReaderProperties rp = new ReaderProperties();
    baos = new MemoryStream(baos.ToArray());
    temp = new PdfDocument(new PdfReader(baos, rp));
    pdfMerger.Merge(temp, 1, temp.GetNumberOfPages());
    temp.Close();
}
pdfMerger.Close();

也许不那么简洁。我用“使用”。 Similar answer

private byte[] CreatePDF(string html)
    {
        byte[] binData;

        using (var workStream = new MemoryStream())
        {
            using (var pdfWriter = new PdfWriter(workStream))
            {
                //Create one pdf document
                using (var pdfDoc = new PdfDocument(pdfWriter))
                {                        
                    pdfDoc.SetDefaultPageSize(iText.Kernel.Geom.PageSize.A4.Rotate());
                    //Create one pdf merger
                    var pdfMerger = new PdfMerger(pdfDoc);
                    //Create two identical pdfs
                    for (int i = 0; i < 2; i++)
                    {
                        using (var newStream = new MemoryStream(CreateDocument(html)))
                        {
                            ReaderProperties rp = new ReaderProperties();
                            using (var newPdf = new PdfDocument(new PdfReader(newStream, rp)))
                            {
                                pdfMerger.Merge(newPdf, 1, newPdf.GetNumberOfPages());
                            }
                        }
                    }
                }
                binData = workStream.ToArray();
            }
        }
        return binData;
    }

创建 pdf

private byte[] CreateDocument(string html)
    {
        byte[] binData;

        using (var workStream = new MemoryStream())
        {
            using (var pdfWriter = new PdfWriter(workStream))
            {
                using (var pdfDoc = new PdfDocument(pdfWriter))
                {
                    pdfDoc.SetDefaultPageSize(iText.Kernel.Geom.PageSize.A4.Rotate());

                    ConverterProperties props = new ConverterProperties();
                    using (var document = HtmlConverter.ConvertToDocument(html, pdfDoc, props))
                    {                            
                    }
                }
                binData = workStream.ToArray();
            }
        }
        return binData;
    }