让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), '\0')) { 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, '\0')) { 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, '\0', true)) { // do stuff } return ms.ToArray(); } 
  • MemoryStream实现了IDisposable ,因此包含using语句。
  • PdfStamper using语句负责处理对象,因此您不需要调用Close() ,也不需要设置CloseStream属性。
  • 您的代码片段在PdfStamper using语句中过早地返回字节数组,因此您的MemoryStream实际上是无操作。 将字节数组返回到PdfStamper using语句之外,并 MemoryStream using语句中返回。
  • 通常,无需重置MemoryStream Position属性。
  • 忽略上面的PdfStamper构造函数 – 它来自我填写表单的一些测试代码,并使用你需要的任何构造函数/方法进行签名。