2013-05-07 2 views
1

Это похоже на то, что нужно делать быстро, но на практике, похоже, проблема. У меня есть куча PDF-форм, которые включают поля формы и встроенный javascript. Я хотел бы удалить код javascript безопасно, но оставить поля формы PDF неповрежденными.Удалить Javascript из PDF с помощью iTextSharp

До сих пор я мог найти множество решений, но все решения либо устранили как поля 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()); 
} 

Кто-нибудь знает, как изменить либо раствор А или В устранить javascript, но оставить поля формы на месте?

EDIT: Код решения находится здесь!

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

ответ

2

Чтобы управлять один PDF вы должны использовать класс PdfStamper и манипулировать его содержимым, в вашем случае итерация над существующие поля формы и удаление записей JavaScript.

Образец iTextSharp AddJavaScriptToForm.cs, соответствующий AddJavaScriptToForm.java из главы 13 iText in Action — 2nd Edition показывает, как 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); 

EDIT:(при условии, Тед 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()); 
} 

EDIT:(по МКЛ) Решение, приведенное выше, несколько перегружено, поскольку оно касается каждого непрямого словарного объекта. С другой стороны, она игнорирует встроенные словари (я не проверил спецификации, хотя, может быть, все /AA, /JS и /JAVASCRIPT записи появляются только в словарях, которые должны быть косвенные объекты, или по крайней мере, с помощью этого кода).

Если выполнение этой задачи было моей работой, я попытался бы получить доступ к объектам, возможно, неся JavaScript более конкретно.

Преимущество этой процедуры перехвата может заключаться в том, что даже объекты PDF проверяются, которые в настоящее время не указаны как несущие JavaScript, но будут в более поздних версиях PDF.

+0

Спасибо! Позвольте мне попробовать и посмотреть, как это происходит. –

+0

Успех! Это сделало работу. Позвольте мне изменить ваш ответ, чтобы точно указать, как читается окончательный код. –

+0

@TedSpence Когда я увидел ваше предложение по редактированию, оно уже было отклонено как * неправильное или попытка ответить или прокомментировать существующее сообщение. * Я включил его здесь, но должен добавить, что ваше решение перехватывает, потому что оно касается каждого и каждый косвенный словарь. С другой стороны, он игнорирует встроенные словари. – mkl

0

Добавьте следующие строки после того, как цикл держать AcroForm:

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

Функция «CopyAcroForm (reader)», похоже, не существует в моем iTextSharp - я загрузил последнюю версию на этой неделе. Возможно, это функция в библиотеке расширений? EDIT - Возможно, вы думаете о 'PdfCopy.CopyAcroForm'. Я проверю это. –

+0

Плохая новость - использование 'PdfCopy.CopyAcroForm' не помогло. Он скопировал все javascript. –

Смежные вопросы