让PdfStamper使用MemoryStreams(c#,itextsharp)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了让PdfStamper使用MemoryStreams(c#,itextsharp)相关的知识,希望对你有一定的参考价值。

我找到了重新编写旧代码的方法,这些代码将PDF文件签名为新文件,这标志着来自Web服务的MemoryStreams(字节数组)。简单吧?那是昨天。今天我无法让它发挥作用。

这是旧代码,它使用FileStreams并且它可以工作:

    public static string OldPdfSigner(PdfReader pdfReader, string destination, string password, string reason, string location, string pathToPfx)
    {
        using (FileStream pfxFile = new FileStream(pathToPfx, FileMode.Open, FileAccess.Read))
        {
            ...

            using (PdfStamper st = PdfStamper.CreateSignature(pdfReader, new FileStream(destination, FileMode.Create, FileAccess.Write), ''))
            {
                PdfSignatureAppearance sap = st.SignatureAppearance;
                sap.SetCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
                sap.Reason = reason;
                sap.Location = location;
                return destination;
            }
        }
    }

下面是我自己重做的内容,它抛出System.ObjectDisposedException:无法访问已关闭的Stream。

    public static byte[] PdfSigner(PdfReader pdfReader, string password, string reason, string location, string pathToPfx)
    {
        using (FileStream pfxFile = new FileStream(pathToPfx, FileMode.Open, FileAccess.Read))
        {
            ...

            MemoryStream outputStream = new MemoryStream();
            using (PdfStamper st = PdfStamper.CreateSignature(pdfReader, outputStream, ''))
            {
                st.Writer.CloseStream = false;
                PdfSignatureAppearance sap = st.SignatureAppearance;
                sap.SetCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
                sap.Reason = reason;
                sap.Location = location;
                st.Close();
                outputStream.Position = 0;
                return outputStream.ToArray();
            }
        }
    }

如果我发表评论

st.Close();

它会创建一个空文档。我究竟做错了什么?

答案

不是特定于您的签名代码,但在使用MemoryStreamPdfStamper时,请遵循以下一般模式:

using (MemoryStream ms = new MemoryStream()) {
  using (PdfStamper stamper = new PdfStamper(reader, ms, '', true)) {
// do stuff      
  }    
  return ms.ToArray();
}
  • MemoryStream实施IDisposable,所以包括using声明。
  • PdfStamper using语句负责处理对象,因此您不需要调用Close(),也不需要设置CloseStream属性。
  • 您的代码片段在PdfStamper using语句中过早返回字节数组,因此您的MemoryStream实际上是无操作。将字节数组返回到PdfStamper using语句之外,并在MemoryStream using语句中返回。
  • 一般来说,没有必要重置MemoryStream Position财产。
  • 忽略上面的PdfStamper构造函数 - 它来自我填写表单的一些测试代码,并使用你需要的任何构造函数/方法进行签名。

以上是关于让PdfStamper使用MemoryStreams(c#,itextsharp)的主要内容,如果未能解决你的问题,请参考以下文章

优势/劣势 MemoryStream.Position 或 MemoryStream.Seek [重复]

使用 MemoryStream 和 CryptoStream 满足代码分析处置规则 [重复]

使用 NAudio 读取包含作品音频的 MemoryStream

使用 StreamWriter 写入 MemoryStream 返回空

MemoryStream相关知识分享

.NET性能优化-使用RecyclableMemoryStream替代MemoryStream