【问题标题】:How to save PDF using ITextSharp?如何使用 ITextSharp 保存 PDF?
【发布时间】:2017-10-11 06:39:28
【问题描述】:

我使用 ITextSharp 处理 PDF 注释。我能够非常顺利地添加注释。 但现在我正在尝试编辑它们。看起来我的 PdfReader 对象实际上已更新。但由于某种原因,我无法保存它。如下面的 sn-p 所示,我尝试使用压模获取字节数组。不管注解多长,字节数组只比之前的版本长1个字节。而且当我打开保存在文件系统上的PDF时,我仍然有旧的注释......

    private void UpdatePDFAnnotation(string title, string body)
    {
        byte[] newBuffer;
        using (PdfReader pdfReader = new PdfReader(dataBuffer))
        {

            int pageIndex = 1;
            int annotIndex = 0;

            PdfDictionary pageDict = pdfReader.GetPageN(pageIndex);
            var annots = pageDict.GetAsArray(PdfName.ANNOTS);
            if (annots != null)
            {
                PdfDictionary annot = annots.GetAsDict(annotIndex);
                annot.Put(PdfName.T, new PdfString(title));
                annot.Put(PdfName.CONTENTS, new PdfString(body));
            }

            // ********************************
            // this line shows the new annotation is in here. Just have to save it somehow !!
            var updatedBody = pdfReader.GetPageN(pageIndex).GetAsArray(PdfName.ANNOTS).GetAsDict(0).GetAsString(PdfName.CONTENTS);
            Debug.Assert(newBody == updatedBody.ToString(), "Annotation body should be equal");


            using (MemoryStream outStream = new MemoryStream())
            {
                using (PdfStamper stamp = new PdfStamper(pdfReader, outStream, '\0', true))
                {
                    newBuffer = outStream.ToArray();
                }
            }

           }
           File.WriteAllBytes( @"Assets\Documents\AnnotedPdf.pdf", newBuffer);
        }

知道我的代码有什么问题吗?

【问题讨论】:

  • 尝试插入 stamp.Close();将 outStream 缓冲区写入 newBuffer 后。
  • @SoumenMukherjee “尝试插入 stamp.Close(); 在将 outStream 缓冲区写入 newBuffer 之后。” - 不是 after 而是 before .

标签: c# pdf itext


【解决方案1】:

PdfStamper 在关闭时进行了大量的写作。这隐含地发生在其using 块的末尾。但是您检索了该块中已经存在的MemoryStream 内容。因此,PDF 尚未写入检索到的byte[]

取而代之的是,在检索 byte[] 之前显式关闭 PdfStamper 实例:

using (PdfStamper stamp = new PdfStamper(pdfReader, outStream, '\0', true))
{
    stamp.Close();
    newBuffer = outStream.ToArray();
}

或检索byte[] 之后 using 块:

using (PdfStamper stamp = new PdfStamper(pdfReader, outStream, '\0', true))
{
}
newBuffer = outStream.ToArray();

【讨论】:

  • 您好,谢谢您的回答。不幸的是,我试过了,但没有用......这让我发疯,因为我可以检查 PdfReader 是最新的,但我只得到过时的字节数组......
  • “我试过了,但没有用” - 如果您执行上述任何一项操作,文件中会写入什么内容?如果您在关闭压模后检索字节(并且在关闭操作期间没有发生异常),那么newBuffer 将包含一个完整的 PDF。 (除非你发现了 iText 错误。但我不这么认为,这种结构很常见。)
【解决方案2】:

好吧,我终于让它工作了。诀窍是 PdfStamper 实例化中的最后两个参数。我之前只用 2 个参数尝试过,结果文件损坏。然后我又试了一次,现在它可以工作了......这是sn-p

    private void UpdatePDFAnnotation(string title, string body)
    {
        using (PdfReader pdfReader = new PdfReader(dataBuffer))
        {
            PdfDictionary pageDict = pdfReader.GetPageN(pageIndex);
            var annots = pageDict.GetAsArray(PdfName.ANNOTS);

            PdfDictionary annot = annots.GetAsDict(annotIndex);
            annot.Put(PdfName.T, new PdfString(title));
            annot.Put(PdfName.CONTENTS, new PdfString(body));

            using (MemoryStream ms = new MemoryStream())
            {
                PdfStamper stamp = new PdfStamper(pdfReader, ms);    
                stamp.Dispose();                
                dataBuffer = ms.ToArray();
            }
        }
    }

【讨论】:

  • 如果带有附加 '\0', true 参数的输出 PDF 被破坏,那么您的原始 PDF 中已经存在一些奇怪的东西。除此之外,这些附加参数不可能导致您观察到的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 2011-12-25
  • 1970-01-01
相关资源
最近更新 更多