【问题标题】:How to add an image to a pdf file in APPEND mode using PdfStamper?如何使用 PdfStamper 在 APPEND 模式下将图像添加到 pdf 文件?
【发布时间】:2016-01-13 15:48:10
【问题描述】:

我正在使用 iTextSharp 库版本 5.5.6.0。 此文件包含可自定义的文本字段,并且有必要保留交互式文本表单字段:https://yadi.sk/i/yoUvDI9EmtVhc。 但我无法在 PdfTemplate 对象中添加图像。 现阶段c#中的代码为:

    string outpath = @"D:\pdf_\output.pdf";
    string inpath = @"D:\pdf_\input.pdf";
    string stamp = @"D:\pdf_\img.png";

此方法不添加图像,但文本框处于活动状态。

            public static void onlyInteractive()
            {
                using (MemoryStream os = new MemoryStream())
                using (PdfReader pdfReader = new PdfReader(inpath))

//APPEND模式

                using (PdfStamper stamper = new PdfStamper(pdfReader, os, '\0', true))
                {
                    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
                    image.SetAbsolutePosition(0, 0);

                    PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
                    template.AddImage(image);

                    stamper.GetOverContent(1).AddTemplate(template, 150, 200, true); 

                    os.WriteTo(new FileStream(outpath, FileMode.Create, FileAccess.ReadWrite));
                }
            }

这个方法的行为回到第一个。

            public static void onlyImage()
            {
                using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
                using (PdfReader reader = new PdfReader(inpath))
                using (var stamper = new PdfStamper(reader, output, '\0', true))
                {
                    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
                    image.SetAbsolutePosition(0, 0);

                    PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
                    template.AddImage(image);

                    stamper.GetOverContent(1).AddTemplate(template, 150, 200, true); 
                }
            }

【问题讨论】:

    标签: pdf itext pdfstamper


    【解决方案1】:

    只有互动

    此代码的问题是您在输出 PDF 完成之前抓取它:

    using (PdfStamper stamper = new PdfStamper(pdfReader, os, '\0', true))
    {
        [...]
        os.WriteTo(new FileStream(outpath, FileMode.Create, FileAccess.ReadWrite));
    }
    

    stamper 关闭时(此处隐式在其using 块的末尾),将写入一些尚未存储的PDF 对象,并写入内部交叉引用和文件尾。

    您在此之前将os 内容写入文件。因此,您的结果文档不完整。 Adobe Reader 在打开它后会对其进行修复,从而基本上生成您的原始文档。

    只有图片

    这段代码本身是正确的,它将图像印在文档上并正确存储。

    您的问题是文档本身是Reader-enabled,即它使用所谓的使用权签名进行签名。此类签名会在打开文件时告知 Adob​​e Reader 以提供显示编辑相关文档的其他功能。

    但是,当使用图像检查文档上的签名时,Adobe Reader 发现文档的更改方式与签名授予的使用权限不兼容:图像已添加到页面内容中,是签名未授予的东西。因此,Adobe Reader 在您的案例表单编辑中撤销授予的功能。

    删除使​​用权签名

    在这种情况下,一个选择是删除该签名。在这种情况下,不再通过该签名授予表单编辑权限。但是在较新的 Adob​​e Reader 版本中(如果我没记错的话,从版本 XI 开始)默认情况下,所有文档都被授予表单编辑功能!在您的情况下,由于签名无效,该功能被删除!

    这可以按如下方式完成:

    using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
    using (PdfReader reader = new PdfReader(inpath))
    using (var stamper = new PdfStamper(reader, output))
    {
        reader.RemoveUsageRights();
        iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
        image.SetAbsolutePosition(0, 0);
    
        PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
        template.AddImage(image);
    
        stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
    }
    

    您现在可以在较新的 Adob​​e Readers 中编辑带有图像的 PDF。

    不幸的是,保存文档时出现错误。我不知道它们是否与源文档部分无效(Adobe Preflight 抱怨许多问题,首先是使用未定义的编码名称 Win1251Encoding)有关,或者是否与否则会损坏。

    在附加模式下移除使用权签名

    追加模式下工作我们必须手动删除使用权限签名。实际上,我们将从 Catalog 中删除整个 Perms 字典:

    using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
    using (PdfReader reader = new PdfReader(inpath))
    using (var stamper = new PdfStamper(reader, output, '\0', true))
    {
        reader.Catalog.Remove(PdfName.PERMS);
        stamper.MarkUsed(reader.Catalog);
        iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
        image.SetAbsolutePosition(0, 0);
    
        PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
        template.AddImage(image);
    
        stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
    }
    

    现在您可以编辑表单并保存文件(至少我可以在 Adob​​e Reader DC 中)。

    PS:正确的坐标

    在评论中,OP 分享了另一个 PDF 并声明它

    对于其他文件,不可能将图片放置在横向页面上。

    OP 的代码确实存在问题:

    stamper.GetOverContent(1).AddTemplate(template, 150, 200, true); 
    

    固定坐标150, 200是OP假定左下角为坐标系原点0, 0的标志。虽然这种情况经常发生,但这并不一定是正确的。必须始终考虑 CropBox(默认为 MediaBox),即对于 OP 的代码:

    Rectangle cropBox = reader.GetCropBox(1);
    stamper.GetOverContent(1).AddTemplate(template, cropBox.Left + 150, cropBox.Bottom + 200, true);
    

    库不正确地进行旋转,但给出了 0 度。

    但这是正确的!您的示例 PDF 有点特别,因为它使用未旋转的矩形表示横向,使用旋转的矩形表示纵向。

    【讨论】:

    • 非常感谢,您的解释很详细。此文件 pdf 的问题已解决,但对于其他文件,无法将图片放置在横向页面上。 yadi.sk/i/kfW4LdxAn3ZVu 在这种情况下你有什么建议?对您的意见感兴趣。
    • 你说的不可能是什么意思?当然有可能,您可能需要使用不同的坐标和一些旋转,仅此而已。
    • 不行,这个文件好像有问题。它包含页面的屏幕截图。并且库不正确地进行旋转,但给出了 0 度。
    • 谢谢,mkl!很有帮助。
    猜你喜欢
    • 2011-12-31
    • 2014-02-17
    • 2015-11-21
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-23
    • 2022-07-15
    相关资源
    最近更新 更多