Как объединить / объединить PDF-файлы с заполняемыми полями формы с помощью iTextSharp? - PullRequest
6 голосов
/ 13 июня 2011

Используя iTextSharp, как я могу объединить несколько PDF-файлов в один PDF, не теряя поля формы и их свойства в каждом отдельном PDF-файле?

(я бы предпочел пример использования потоков из базы данных, но с файловой системой тоже все в порядке)

Я нашел этот код , который работает, но он выравнивает мои PDF-файлы, поэтому я не могу его использовать.

UPDATE

@ Mark Storer - это код, который я сейчас использую на основе ваших отзывов (см. Ниже), но он дает мне поврежденный документ после сохранения. Я протестировал каждую из частей кода по отдельности, и, похоже, что она не работает в функции MergePdfForms, показанной ниже. Я, очевидно, не хочу использовать renameFields часть вашего примера, потому что мне нужно, чтобы имена полей оставались «как есть».

Public Sub MergePdfForms(ByVal pdfFiles As ArrayList, ByVal outputPath As String)
    Dim ms As New IO.MemoryStream()
    Dim copier As New PdfCopyFields(ms)
    For Each pfile As String In pdfFiles
        Dim reader As New PdfReader(pfile)
        copier.AddDocument(reader)
    Next
    SaveMemoryStream(ms, outputPath)
    copier.Close()
End Sub

Public Sub SaveMemoryStream(ms As IO.MemoryStream, FileName As String)
    Dim outStream As IO.FileStream = IO.File.OpenWrite(FileName)
    ms.WriteTo(outStream)
    outStream.Flush()
    outStream.Close()
End Sub

Ответы [ 3 ]

11 голосов
/ 13 июня 2011

Поля в PDF-файлах имеют необычное свойство: все поля с одинаковым именем 1002 * являются одинаковыми полем .Они разделяют ценность.Это удобно, когда форма относится к одному и тому же человеку, и у вас есть хорошая схема именования для всех форм.Это не удобно, если вы хотите поместить 20 экземпляров одной формы в один файл PDF.

Это затрудняет объединение нескольких форм, если не сказать больше.Наиболее распространенный вариант (благодаря iText) - это выравнивание форм перед их объединением, после чего вы больше не объединяете формы, и проблема уходит.

Другой вариант - переименовать вашполя до слияния их.Это может впоследствии затруднить извлечение данных, нарушить работу сценариев и обычно является PITA.Вот почему сглаживание намного популярнее.

В iText есть класс с именем PdfCopyFields, и он будет правильно копировать поля из одного документа в другой ... он также объединит поля с тем же именем правильно , так что они действительно разделяют одно значение, и Acrobat / Reader не нужно выполнять кучу дополнительной работы с файлом, чтобы получить его таким образом, прежде чем отобразить его пользователю.

Однако PdfCopyFields не будет переименовывать поля для вас.Для этого вам нужно получить объект AcroFields у рассматриваемого PdfReader и вызвать renameField(String, String) в каждом поле перед каждым объединением документов с PdfCopyFields.

Все этодля PDF-форм на основе AcroForm.Если вы имеете дело с формами XFA (формами из LiveCycle Designer), все ставки отменены.Вам придётся разбираться с XML, много.

И небеса помогут вам, если вам придется комбинировать формы из обоих.

Настолько, что вы работаете сПоля AcroForm, код может выглядеть примерно так (простите за Java):

public void mergeForms(String outpath, String inPaths[]) {
  PdfCopyFields copier = new PdfCopyFields(new FileOutputStream(outpath) );
  for (String curInPath : inPaths) {
    PdfReader reader = new PdfReader(curInPath);
    renameFields(reader.getAcroFields());

    copier.addDocument(reader);
  }
  copier.close();
}

private static int counter = 0;
private void renameFields(AcroFields fields) {
  Set<String> fieldNames = fields.getFields().keySet();
  String prepend = String.format("_%d.", counter++);

  for(String fieldName : fieldNames) {
    fields.rename(fieldName, prepend + fieldName);
  }
}

В идеале renameFields также создаст объект общего поля с именем prepend's-value и сделает все остальные поля в документеэто дети.Это облегчит жизнь Acrobat / Reader и позволит избежать ненужных «сохранения изменений»?запрашивать при закрытии полученного PDF от Acrobat.

Да, именно поэтому Acrobat иногда просит вас сохранить изменения, когда вы ничего не сделали!Acrobat сделал что-то за кадром.

2 голосов
/ 09 января 2013

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

    Document document = new Document();
    try
        {         
           string destinationfile = desktopPath.Replace(@"d:\outputfile.pdf");
           PdfCopyFields copier = new PdfCopyFields(new FileStream(destinationfile,     FileMode.Create));
            PdfImportedPage page;

            //Loops for each file that has been listed
            foreach (string filename in fileList)
            {
                flag++;
                try
                {
                    //The current file path
                    string filePath = sourcefolder + filename;

                    PdfReader reader = new PdfReader(filePath);
                    copier.AddDocument(reader);

                }
                catch
                {

                }
            }
            copier.Close();
        }
0 голосов
/ 13 июня 2011
...