【问题标题】:Merging N pdf files, created from html using ITextSharp, to another blank pdf file将使用 ITextSharp 从 html 创建的 N 个 pdf 文件合并到另一个空白 pdf 文件
【发布时间】:2017-03-17 01:10:52
【问题描述】:

我需要将 N 个 PDF 文件合并为一个。我先创建一个空白文件

byte[] pdfBytes = null;

var ms = new MemoryStream();
var doc = new iTextSharp.text.Document();
var cWriter = new PdfCopy(doc, ms);

稍后我循环遍历 html 字符串数组

foreach (NBElement htmlString in someElement.Children())
                    {
                        byte[] msTempDoc = getPdfDocFrom(htmlString.GetString(), cssString.GetString());
                        addPagesToPdf(cWriter, msTempDoc);
                    }

在 getPdfDocFrom 中,我使用 XMLWorkerHelper 创建 pdf 文件并将其作为字节数组返回

private byte[] getPdfDocFrom(string htmlString, string cssString)
    {
        var tempMs = new MemoryStream();
        byte[] tempMsBytes;
        var tempDoc = new iTextSharp.text.Document();
        var tempWriter = PdfWriter.GetInstance(tempDoc, tempMs);
        tempDoc.Open();

        using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(cssString)))
        {
            using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(htmlString)))
            {
                //Parse the HTML
                iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(tempWriter, tempDoc, msHtml, msCss);
                tempMsBytes = tempMs.ToArray();
            }
        }

        tempDoc.Close();
        return tempMsBytes;
    }

稍后我尝试将此 PDF 文件中的页面添加到空白文件中。

private static void addPagesToPdf(PdfCopy mainDocWriter,  byte[] sourceDocBytes)
    {

        using (var msOut = new MemoryStream())
        {
            PdfReader reader = new PdfReader(new MemoryStream(sourceDocBytes));
            int n = reader.NumberOfPages;
            PdfImportedPage page;
            for (int i = 1; i <= n; i++)
            {
                page = mainDocWriter.GetImportedPage(reader, i);
                mainDocWriter.AddPage(page);
            }
        }}

当它尝试从我传递给函数的字节数组创建 PdfReader 时,它会中断。 “重建失败:未找到预告片。原始消息:未找到 PDF startxref。”

我以前使用另一个库来处理 PDF。我将 2 个 PdfDocuments 作为对象传递,只是循环添加页面。不过它不支持 Css,所以我不得不切换到 ITextSharp。

我不太明白 PdfWriter 和 PdfCopy 之间的区别。

【问题讨论】:

    标签: c# pdf itext


    【解决方案1】:

    您的代码中存在逻辑错误。当您像在getPdfDocFrom() 方法中那样从头开始创建文档时,在您触发Close() 方法之前,该文档并不完整。在这个Close() 方法中,创建了一个预告片以及一个交叉引用(xref) 表。错误告诉你那些丢失了。

    确实,您确实调用了Close() 方法:

    tempDoc.Close();
    

    但是当您Close() 文档时,为时已晚:您已经创建了tempMsBytes 数组。您需要在关闭文档后创建该数组

    编辑:我对C#一无所知,但是如果MemoryStream在关闭它后清除了它的缓冲区,你可以使用mainDocWriter.CloseStream = false;这样MemoryStream在关闭时不会关闭你关闭文档。

    在 Java 中,将“关闭流”参数设置为 false 是个坏主意。当我阅读Create PDF in memory instead of physical file 问题的答案时,我发现 C# 可能并不总是需要这个额外的行。

    备注:通过将PdfImportedPage 实例添加到PdfWriter 来合并文件是一个糟糕的例子。如果您使用的是 iTextSharp 5 或更早版本,则应使用 PdfCopyPdfSmartCopy 来执行此操作。如果你使用PdfWriter,你会丢掉很多信息(例如链接注释)。

    【讨论】:

    • 但是我关闭文档后 MemoryStream 变空了。我无法从中创建字节数组
    • 这可能就是人们使用mainDocWriter.CloseStream = false;的原因我是一名Java开发人员,我很难理解为什么C#在关闭内存流后会清空它。 C# 有一些我无法完全理解的奇怪奥秘。例如,这似乎有效:stackoverflow.com/questions/2815761/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多