29

我想重新编写旧代码,将 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:无法访问关闭的流。

    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();

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

4

1 回答 1

30

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

using (MemoryStream ms = new MemoryStream()) {
  using (PdfStamper stamper = new PdfStamper(reader, ms, '\0', true)) {
// do stuff      
  }    
  return ms.ToArray();
}
  • MemoryStreamimplements IDisposable,所以包括一个using声明。
  • PdfStamper using语句负责处理对象,因此您不需要调用Close(),也不需要设置CloseStream属性。
  • 您的代码片段在语句中过早返回字节数组,因此您实际上是无操作的。返回语句外部和语句内部的字节数组。PdfStamper usingMemoryStreamPdfStamper usingMemoryStream using
  • 一般不需要重置MemoryStream Position属性。
  • 忽略PdfStamper上面的构造函数 - 它来自我用于填写表格的一些测试代码,并使用您需要进行签名的任何构造函数/方法。
于 2014-11-30T01:15:50.150 回答