【问题标题】:C# Add PDF Encryption to Multiple MemoryStreams - Cannot access a closed StreamC# 将 PDF 加密添加到多个 MemoryStreams - 无法访问已关闭的流
【发布时间】:2018-05-15 11:05:03
【问题描述】:

是否可以为从多个 MemoryStreams 动态创建的 PDF 添加加密?

继上一个问题C# Append PDF file to MemoryStream - Cannot access a closed Stream 之后,我正在尝试添加 PDF 加密。

从我在下面提供的示例中,如果注释掉 pdfStamper.Close(); 行,我不会收到错误 Cannot access a closed Stream,但也不会对生成的 PDF 应用加密。

有人可以告诉我哪里出错了,如果可能的话如何解决我的问题?

public MemoryStream CreateMemoryStream()
{
    byte[] dynamicPdfBytes;

    using (var dynamicPDfMemoryStream = new MemoryStream())
    {
        using (var document = new Document(PageSize.A4, 25, 25, 30, 30))
        {
            PdfWriter.GetInstance(document, dynamicPDfMemoryStream);

            document.Open();

            var pdfPTable = new PdfPTable(1)
            {
                TotalWidth = _totalWidth,
                LockedWidth = true,
                SpacingBefore = _spacingBefore,
                SpacingAfter = _spacingAfter
            };

            float[] widths = { 272f };

            pdfPTable.SetWidths(widths);

            var image = Image.GetInstance(HttpContext.Current.Server.MapPath("/Images/logo.png"));
            image.ScaleToFit(125f, 125f);
            image.Alignment = Image.RIGHT_ALIGN;

            var pdfPCell = new PdfPCell(image)
            {
                Border = 0,
                HorizontalAlignment = Element.ALIGN_RIGHT
            };

            pdfPTable.AddCell(pdfPCell);

            document.Add(pdfPTable);
        }

        dynamicPdfBytes = dynamicPDfMemoryStream.ToArray();
    }

    byte[] pdfBytes;

    using (var pdfReader = new PdfReader(HttpContext.Current.Server.MapPath("/Documents/Test.pdf")))
    {
        using (var pdfMemoryStream = new MemoryStream())
        {
            var pdfStamper = new PdfStamper(pdfReader, pdfMemoryStream);

            var acroFields = pdfStamper.AcroFields;
            acroFields.SetField("TestField", "This is a test");
            pdfStamper.FormFlattening = true;
            pdfStamper.Close();

            pdfBytes = pdfMemoryStream.ToArray();
        }
    }

    var files = new List<byte[]> { dynamicPdfBytes, pdfBytes };

    byte[] array;

    using (var arrayMemoryStream = new MemoryStream())
    {
        var document = new Document(PageSize.A4, 25, 25, 30, 30);

        var pdfWriter = PdfWriter.GetInstance(document, arrayMemoryStream);

        document.Open();

        var directContent = pdfWriter.DirectContent;

        foreach (var bytes in files)
        {
            var pdfReader = new PdfReader(bytes);

            var pdfStamper = new PdfStamper(pdfReader, arrayMemoryStream);
            pdfStamper.SetEncryption(null, _password, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);

            var numberOfPages = pdfReader.NumberOfPages;

            for (var i = 1; i <= numberOfPages; i++)
            {
                document.NewPage();

                var page = pdfWriter.GetImportedPage(pdfReader, i);

                directContent.AddTemplate(page, 0, 0);
            }

            pdfStamper.FormFlattening = true;
            pdfStamper.Close();
        }

        document.Close();

        array = arrayMemoryStream.ToArray();
    }

    var memoryStream = new MemoryStream();
    memoryStream.Write(array, 0, array.Length);
    memoryStream.Position = 0;

    return memoryStream;
}

任何帮助将不胜感激:-)

【问题讨论】:

  • 对于这个网站上的一些用户来说,这是一种耻辱,而不是贬低用户可能没有按照他人的理想编码或可能没有正确地表达问题,也许用户可以提供更多帮助的阻碍,只是一个想法!
  • 参见 stackoverflow.com/questions/28566190/… 以获取涉及表单的 PdfCopy 示例。这也会有帮助:stackoverflow.com/questions/33582996/… PdfCopy 对象也有一个 SetEncryption() 方法,如下所述:stackoverflow.com/questions/17719629/…
  • 请注意,您使用的是旧版本的 iText。您确实应该升级到 iText 7,因为不再支持 iText 5(或更早版本)。请不要在生产中使用您在此问题中编写的代码。如果您的客户看到您的代码,他可能会不高兴。如果您的客户没有看到您的代码,请注意 iText 是根据 AGPL 获得许可的,并且不与您的客户共享您的代码意味着您需要购买商业许可证才能使用 iText。

标签: c# pdf encryption itext


【解决方案1】:

这可能不是最优雅的解决方案,但它是针对这个特定问题的解决方案,我希望它对其他人有用。

下面的代码可以与原始示例代码结合使用,只需将上面代码中所有pdfStamper引用注释掉即可:

private MemoryStream SecureMemoryStream()
{
    var memoryStream = CreateMemoryStream();

    return GetSecureMemoryStream(memoryStream);
}

private MemoryStream GetSecureMemoryStream(MemoryStream memoryStream)
{
    byte[] array;

    using (var secureMemoryStream = new MemoryStream())
    {
        var pdfReader = new PdfReader(memoryStream);

        using (var pdfStamper = new PdfStamper(pdfReader, secureMemoryStream))
        {
            pdfStamper.SetEncryption(null, _password, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
            pdfStamper.FormFlattening = true;
        }

        array = secureMemoryStream.ToArray();
    }

    var outputStream = new MemoryStream();
    outputStream.Write(array, 0, array.Length);
    outputStream.Position = 0;

    return outputStream;
}

【讨论】:

  • 这没有帮助。您的 GetSecureMemoryStream() 方法会加密单个 PDF 文件(如果有的话,它还会使所有表单字段变平)。问题是如何合并 PDF 文件。当我试图在我的 cmets 中解释时,选项 1 是使用 PdfCopy(或 PdfSmartCopy)。选项 2 是升级到 iText 7,因为不再支持 OP 使用的 iText 版本。
猜你喜欢
  • 2018-10-14
  • 2011-01-20
  • 2023-03-12
  • 2011-12-27
  • 2012-06-11
  • 2021-12-21
  • 2017-01-12
  • 1970-01-01
  • 2021-01-08
相关资源
最近更新 更多