这似乎应该是快速做的事情,但在实践中似乎存在问题。我有一堆PDF表单,包括表单字段和嵌入式JavaScript。我想安全地删除javascript代码,但保留PDF表单字段不变。
到目前为止,我已经找到了很多解决方案,但所有解决方案都要么已经删除了javascript和表单字段,要么保留原样。
这是解决方案A;它复制表单字段和javascript:
var pdfReader = new PdfReader(infilename);
using (MemoryStream memoryStream = new MemoryStream()) {
PdfCopyFields copy = new PdfCopyFields(memoryStream);
copy.AddDocument(pdfReader);
copy.Close();
File.WriteAllBytes(rawfilename, memoryStream.ToArray());
}
或者,我有解决方案B,它会删除表单字段和javascript:
Document document = new Document();
using (MemoryStream memoryStream = new MemoryStream()) {
PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
document.Open();
document.AddDocListener(writer);
for (int p = 1; p <= pdfReader.NumberOfPages; p++) {
document.SetPageSize(pdfReader.GetPageSize(p));
document.NewPage();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage pageImport = writer.GetImportedPage(pdfReader, p);
int rot = pdfReader.GetPageRotation(p);
if (rot == 90 || rot == 270) {
cb.AddTemplate(pageImport, 0, -1.0F, 1.0F, 0, 0, pdfReader.GetPageSizeWithRotation(p).Height);
} else {
cb.AddTemplate(pageImport, 1.0F, 0, 0, 1.0F, 0, 0);
}
}
document.Close();
File.WriteAllBytes(rawfile, memoryStream.ToArray());
}
是否有人知道如何修改解决方案A或B以消除javascript但保留表单字段?
编辑:解决方案代码在这里!
using (MemoryStream memoryStream = new MemoryStream()) {
PdfStamper stamper = new PdfStamper(pdfReader, memoryStream);
for (int i = 0; i <= pdfReader.XrefSize; i++) {
object o = pdfReader.GetPdfObject(i);
PdfDictionary pd = o as PdfDictionary;
if (pd != null) {
pd.Remove(PdfName.AA);
pd.Remove(PdfName.JS);
pd.Remove(PdfName.JAVASCRIPT);
}
}
stamper.Close();
pdfReader.Close();
File.WriteAllBytes(rawfile, memoryStream.ToArray());
}
答案 0 :(得分:3)
要操作单个PDF,您应该使用类PdfStamper
并操纵其内容,在您的情况下迭代现有表单字段并删除JavaScript条目。
AddJavaScriptToForm.cs第13章中与AddJavaScriptToForm.java对应的iTextSharp示例iText in Action — 2nd Edition显示了如何添加到字段,中央代码为:
PdfStamper stamper = new PdfStamper(reader, ms);
AcroFields form = stamper.AcroFields;
AcroFields.Item fd = form.GetFieldItem("married");
PdfDictionary dictYes = (PdfDictionary) PdfReader.GetPdfObject(fd.GetWidgetRef(0));
PdfDictionary yesAction = ...;
dictYes.Put(PdfName.AA, yesAction);
因此,要删除此类JavaScript表单字段操作,您必须遍历所有这些PDF表单字段并删除 / AA 值相关的词典:
dictXXX.Remove(PdfName.AA);
编辑: (由Ted Spence提供)以下是成功删除javascript同时保留所有表单字段的最终代码:
using (MemoryStream memoryStream = new MemoryStream())
{
PdfStamper stamper = new PdfStamper(pdfReader, memoryStream);
for (int i = 0; i <= pdfReader.XrefSize; i++)
{
PdfDictionary pd = pdfReader.GetPdfObject(i) as PdfDictionary;
if (pd != null)
{
pd.Remove(PdfName.AA); // Removes automatic execution objects
pd.Remove(PdfName.JS); // Removes javascript objects
pd.Remove(PdfName.JAVASCRIPT); // Removes other javascript objects
}
}
stamper.Close();
pdfReader.Close();
File.WriteAllBytes(rawfile, memoryStream.ToArray());
}
编辑: (通过mkl)上面的解决方案有点过于成功,因为它会触及每个间接字典对象。另一方面它忽略了内联词典(我没有检查过规范;也许所有 / AA , / JS 和 / JAVASCRIPT 条目仅出现在必须是间接对象的字典中,或至少被此代码取消引用。
如果履行这项任务是我的工作,我会尝试更具体地访问可能带有JavaScript的对象。
这种超额完成程序的优点可能是,即使是PDF对象也会被检查,这些对象目前未指定为携带JavaScript,但将在以后的PDF版本中使用。
答案 1 :(得分:0)
在for循环后添加以下行以保留AcroForm:
var form = pdfReader.AcroForm;
if (form != null)
writer.CopyAcroForm(reader);