【问题标题】:Remove Javascript from PDF using iTextSharp使用 iTextSharp 从 PDF 中删除 Javascript
【发布时间】:2013-04-30 19:55:26
【问题描述】:

这似乎应该很快就完成,但在实践中似乎存在问题。我有一堆包含表单域和嵌入式 javascript 的 PDF 表单。我想安全地删除 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());
}

【问题讨论】:

    标签: c# pdf itextsharp


    【解决方案1】:

    要操作单个 PDF,您应该使用 PdfStamper 类并操作其内容,在您的情况下迭代现有表单字段并删除 JavaScript 条目。

    iText in Action — 2nd Edition 第 13 章中的AddJavaScriptToForm.java 对应的 iTextSharp 示例 AddJavaScriptToForm.cs 显示了 JavaScript 操作是如何添加到字段中的,中心代码是:

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

    编辑: (by mkl) 上面的解决方案有点过头了,因为它涉及到每个间接字典对象。另一方面,它忽略了内联字典(不过,我还没有检查过规范;可能所有的 /AA/JS/JAVASCRIPT > 条目只出现在必须是间接对象的字典中,或者至少被此代码取消引用)。

    如果完成这项任务是我的工作,我会尝试更具体地访问可能携带 JavaScript 的对象。

    不过,这种超额完成过程的优势可能在于,即使是目前未指定为携带 JavaScript 但将在以后的 PDF 版本中出现的 PDF 对象也会被检查。

    【讨论】:

    • 谢谢!让我试一试,看看效果如何。
    • 成功!这完成了这项工作。让我修改您的答案,以准确说明最终代码的读取方式。
    • @TedSpence 当我看到您的编辑提案时,它已被拒绝,因为不正确或试图回复或评论现有帖子。我将其包含在此处但有补充一点,您的解决方案过于出色,因为它触及了每一个间接字典对象。另一方面,它忽略了内联字典。
    • 关于 PDF 规范肯定有很多东西要学。我很想创建一个更强大的解决方案,所以如果有办法改进它,我很乐意看到它们。
    【解决方案2】:

    在 for 循环之后添加以下行以保留 AcroForm:

    var form = pdfReader.AcroForm;
    if (form != null)
       writer.CopyAcroForm(reader);
    

    【讨论】:

    • 我的 iTextSharp 中似乎不存在“CopyAcroForm(reader)”功能 - 我本周下载了最新版本。这可能是扩展库中的一个函数吗?编辑-您可能正在考虑PdfCopy.CopyAcroForm。我会检查一下。
    • 坏消息 - 使用 PdfCopy.CopyAcroForm 不起作用。它复制了所有的javascript。
    猜你喜欢
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    相关资源
    最近更新 更多