如何使用PdfStamper在APPEND模式下将图像添加到pdf文件?

时间:2016-01-13 15:48:11

标签: pdf itext pdfstamper

我正在使用 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); 
                }
            }

1 个答案:

答案 0 :(得分:1)

onlyInteractive

此代码的问题在于您在输出完成之前获取输出PDF:

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

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

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

onlyImage

此代码本身是正确的,它会将图像标记到文档上并正确存储。

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

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

删除使​​用权签名

此情况下的一个选项是删除该签名。在这种情况下,表格编辑不再通过该签名授予。但是在较新的Adobe 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);
}

您现在可以在较新的Adobe读者中使用图像编辑PDF。

不幸的是,保存文档时出错。我不知道他们是否与源文档部分无效这一事实有关(Adobe Preflight抱怨许多问题,最重要的是使用未定义的编码名称 Win1251Encoding )或是否有其他东西被打破。

在附加模式中删除使用权签名

使用追加模式,我们必须手动删除使用权签名。实际上,我们会从目录中删除整个 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);
}

现在您可以编辑表单并保存文件(至少我可以在Adobe 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有点特殊,因为它使用未旋转的矩形用于横向,而旋转的矩形用于纵向。