Получение PdfStamper для работы с MemoryStreams (C#, itextsharp)

Мне пришло в голову переделать старый код, который подписывает файлы PDF в новый, который подписывает 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();

он создает пустой документ. Что я делаю неправильно?

1 ответ

Решение

Не зависит от вашего кода подписи, но при работе с MemoryStream а также PdfStamper, следуйте этой общей схеме:

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 имущество.
  • Ваш фрагмент кода возвращает байтовый массив слишком рано, внутри PdfStamperusing заявление, так что ваш MemoryStream это фактически неоперация. Вернуть массив байтов за пределы PdfStamperusing заявление, а внутри MemoryStream using заявление.
  • Обычно нет необходимости сбрасывать MemoryStreamPosition имущество.
  • Игнорировать PdfStamper Конструктор выше - это из некоторого тестового кода, который у меня был для заполнения форм и использования любого конструктора / метода, который вам нужен для подписи.
Другие вопросы по тегам