0

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

//追加模式

                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); 
                }
            }
4

1 回答 1

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 在打开它时会对其进行修复,这基本上会产生您的原始文档。

只有图像

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

您的问题是文档本身是启用阅读器的,即它使用所谓的使用权限签名进行签名。此类签名会在打开文件时告知 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)或是否有其他问题有关。

删除附加模式下的使用权限签名

附加模式下工作,我们必须手动删除使用权限签名。实际上,我们将从目录中删除整个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 有点特别,因为它使用未旋转的矩形表示横向,使用旋转的矩形表示纵向。

于 2016-01-14T11:45:17.427 回答