【问题标题】:Getting PdfStamper to work with MemoryStreams (c#, itextsharp)让 PdfStamper 与 MemoryStreams 一起工作(c#,itextsharp)
【发布时间】:2015-01-27 02:37:12
【问题描述】:

我想重新编写将 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: Cannot access a closed 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();

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

【问题讨论】:

  • 看看this answer
  • 签名的安全性不是我的责任。我的唯一职责是将签名应用于 MemoryStream 而不是 FileStream。我确实在st.Close(); 之前放了st.Writer.CloseStream = false;,谁能帮我签署一个MemoryStream,好吗?

标签: c# pdf itext memorystream pdfstamper


【解决方案1】:

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

using (MemoryStream ms = new MemoryStream()) {
  using (PdfStamper stamper = new PdfStamper(reader, ms, '\0', true)) {
// do stuff      
  }    
  return ms.ToArray();
}
  • MemoryStream 实现 IDisposable,因此包含 using 语句。
  • PdfStamperusing 语句负责处理对象,因此您无需调用Close(),也无需设置CloseStream 属性。
  • 您的代码 sn-p 在PdfStamper using 语句中返回字节数组太快了,因此您的MemoryStream 实际上是一个空操作。返回PdfStamperusing语句外部MemoryStreamusing语句内部的字节数组。
  • 一般不需要重置MemoryStreamPosition属性。
  • 忽略上面的 PdfStamper 构造函数 - 它来自我用于填写表单的一些测试代码,并使用您进行签名所需的任何构造函数/方法。

【讨论】:

  • 谢谢你,@kuujinbo,你是救生员。现在我该如何摆脱那个反对票,因为这个问题是完全合法的?
  • @ADSMarko:只是 SO 的一个特质,所以不要让它影响到你。 :) 无论出于何种原因,有人不喜欢你的问题。对于它的价值,如果我认为这不是一个合理的问题,并且看到 很多 更糟糕的是没有被否决,所以你得到了我的支持。如果可能,请考虑更改问题标题以反映直接的 PdfStamper / MemoryStream 关系,因为这是根本问题。
  • 会的,@kuujinbo。谢谢
  • PdfStamper 似乎不再实现 IDisposable
  • 仅供参考...如果您在调用 ToArray() 之前将 MemoryStream 位置重置为 0,您将收到一个异常,指出您无法访问已关闭的流 - 即使在内存流内部使用。 ToArray 本身不会抛出。我猜 PdfStamper 会关闭它。
猜你喜欢
  • 2014-08-01
  • 2016-12-13
  • 2016-10-06
  • 2011-11-30
  • 2014-02-19
  • 2011-09-03
  • 2013-05-01
  • 2018-05-30
  • 2014-03-17
相关资源
最近更新 更多