【问题标题】:Generate one pdf document with multiple pages converting from html using IText 7使用 IText 7 生成一个包含从 html 转换的多页的 pdf 文档
【发布时间】:2019-12-16 08:38:28
【问题描述】:

我正在使用IText 7,我已经能够获取一个 html 页面并为该页面生成一个 pdf,但我需要从多个 html 页面生成一个 pdf 文档并按页面分隔。例如:我有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,然后只生成一个 pdf,每个 html 页面只有一个页面?

更新

我一直在关注 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();

【问题讨论】:

  • “是否可以针对多个 html 页面进行循环” - 您是否尝试过创建该循环?它以何种方式失败? (因为确实,它应该是可能的。)
  • 最好的解决方案是在内存中生成这些文档并使用PdfMerger将它们合并到一个单独的fat文件中
  • @mkl 我已经更新了我的问题,我正在尝试这样做,但我收到了一个异常
  • @AlexeySubach 感谢您的建议,我正在尝试使用PdfMerger,但仍然无法使用,我已经更新了我的问题,有什么建议吗?

标签: c# pdf itext pdf-generation itext7


【解决方案1】:

您正在使用RandomAccessSourceFactory 并在那里传递一个您将PDF 文档写入其中的封闭流。 RandomAccessSourceFactory 期望输入流,而不是准备好读取。

首先,您应该使用 .NET 世界原生的 MemoryStreamByteArrayOutputStream 是从 Java 移植用于内部目的的类(尽管它也扩展了 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();

【讨论】:

  • 我希望我能再给这个答案投票 5 次,谢谢!!!已经为此苦苦挣扎了一段时间...
【解决方案2】:

也许不是那么简洁。我使用“使用”。 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;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-05
    • 2020-12-08
    • 1970-01-01
    • 2020-12-11
    • 2021-10-03
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多