首页 文章

将使用ITextSharp从html创建的N个pdf文件合并到另一个空白pdf文件中

提问于
浏览
1

我需要将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之间的区别 .

1 回答

  • 0

    您的代码中存在逻辑错误 . 当您从头开始创建文档时,如 getPdfDocFrom() 方法中所做的那样,文档未触发 Close() 方法 . 在此 Close() 方法中,将创建预告片以及交叉引用(外部参照)表 . 该错误告诉您缺少那些 .

    实际上,你确实调用 Close() 方法:

    tempDoc.Close();
    

    但到了你的文件时,为时已晚:你已经创建了 tempMsBytes 数组 . 关闭文档后需要创建该数组 .

    Edit: 我对C#一无所知,但是如果 MemoryStream 在关闭它后清除其缓冲区,则可以使用 mainDocWriter.CloseStream = false; ,以便在关闭文档时不关闭 MemoryStream .

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

    Remark: 通过将 PdfImportedPage 实例添加到 PdfWriter 来合并文件是一个不好品味的例子 . 如果您使用的是iTextSharp 5或更早版本,则应使用 PdfCopyPdfSmartCopy 来执行此操作 . 如果您使用 PdfWriter ,则会丢弃大量信息(例如链接注释) .

相关问题