我正在使用 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);
}
}
答案 0 :(得分:1)
此代码的问题在于您在输出完成之前获取输出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在打开它时会对其进行修复,从而导致基本上是原始文档。
此代码本身是正确的,它会将图像标记到文档上并正确存储。
您的问题是文档本身是 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中)。
在评论中,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有点特殊,因为它使用未旋转的矩形用于横向,而旋转的矩形用于纵向。