2015-11-07 2 views
1

У меня ниже iText код для чтения файлов и добавления его в главный файл PDF, поэтому он в основном добавляет страницу PDF в существующий PDF в абсолютном положении. Абсолютное положение и номер страницы в главном PDF-документе будут определяться динамически. Иногда это может быть на стр. 1 с 100,100(x,y) или стр. 2 с 250,250(x,y). Я просматриваю объекты PDF, где каждый объект представляет файл PDF, затем я буду применять бизнес-логику для преобразования PDF-объекта в файл PDF, а это srcPdf. Теперь мне нужно, чтобы добавить этот srcPdf в абсолютной позиции в мастер PDF (который pdfStamper здесь):Лучший подход к использованию PdfStamper in for loop

for(ListOfPdfObject pdfObj: ListOfPdfObjects) { 
    // code to create srcPdf so there will be new srcPdf for each iteration. srcPdf is flattened pdf of acro form field pdf. 
    PdfReader reader2 = new PdfReader(srcPdf.getAbsolutePath()); 
    PdfImportedPage page = pdfStamper.getImportedPage(reader2, 1); 
    pdfStamper.insertPage(1, reader2.getPageSize(1)); 
    pdfStamper.getUnderContent(1).addTemplate(page, 100, 100); 
    pdfStamper.close(); // problem is here 
    reader2.close(); 
} 

Здесь pdfStamper создается за пределами for-loop, как показано ниже:

PdfReader pdfReader = new PdfReader(new FileInputStream(tempPdf)); 
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(destPdf)); 

Проблема заключается в том, если я закрою pdfStamper после for-loop it throws RandomAccessSource not opened исключение. Если я закрою внутри цикла, мне придется снова создать внутри for-loop. Не могли бы вы указать мне в правильном направлении.

ответ

2

Как пояснялось в моем ответе Extract pdf page and insert into existing pdf, использование PdfStamper - это только один из способов удовлетворить ваши требования. PdfStamper, вероятно, ваш лучший выбор, если вам нужно манипулировать единственным документом PDF, и можно добавить одну страницу от еще один PDF, как показывает мой предыдущий ответ.

Однако теперь вы указываете, что вам нужно объединить несколько файлов PDF. В этом случае использование PdfStamper - не лучший выбор. Вы должны переходить на PdfCopy:

Предположим, что у вас есть следующие файлы.

String[] paths = new String[]{ 
    "resources/to_be_inserted_1.pdf", 
    "resources/to_be_inserted_2.pdf", 
    "resources/to_be_inserted_3.pdf" 
}; 

Вам необходимо вставить первую страницу (и только первую страницу) каждый из этих документов в начале существующего PDF с путем "resources/main_document.pdf", то вы могли бы сделать что-то вроде этого:

Document document = new Document(); 
PdfCopy copy = new PdfCopy(document, new FileOutputStream(dest)); 
document.open(); 
PdfReader reader; 
for (String path : paths) { 
    reader = new PdfReader(path); 
    copy.addPage(copy.getImportedPage(reader, 1)); 
    reader.close(); 
} 
reader = new PdfReader("resources/main_document.pdf"); 
copy.addDocument(reader); 
reader.close(); 
document.close(); 

Как вы можете видеть, метод addPage() добавляет одну страницу, тогда как метод addDocument() добавляет все страницы документа.

Update

кажется, что вы не хотите, чтобы вставки новых страниц, но что вы хотите накладываться страницы: Вы хотите добавить страницы поверх или под существующий контент.

В этом случае вам действительно нужно PdfStamper, но вы делаете две важные ошибки.

  1. Вы закрываете stamper внутри цикла. Как только stamper закрыт, он закрыт: вы не можете добавить к нему больше контента. Вам нужно переместить stamper.close() вне цикла.
  2. Вы закрываете reader внутри петли, но stamper не имеет освобожденreader. Вы должны бесплатно читатель первым.

Это показано в SuperImpose Например:

public static final String SRC = "resources/pdfs/primes.pdf"; 
public static final String[] EXTRA = 
    {"resources/pdfs/hello.pdf", "resources/pdfs/base_url.pdf", "resources/pdfs/state.pdf"}; 
public static final String DEST = "results/stamper/primes_superimpose.pdf"; 

PdfReader reader = new PdfReader(SRC); 
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(DEST)); 
PdfContentByte canvas = stamper.getUnderContent(1); 
PdfReader r; 
PdfImportedPage page; 
for (String path : EXTRA) { 
    r = new PdfReader(path); 
    page = stamper.getImportedPage(r, 1); 
    canvas.addTemplate(page, 0, 0); 
    stamper.getWriter().freeReader(r); 
    r.close(); 
} 
stamper.close(); 

В этом случае, я всегда добавляю импортированные страницы на страницу 1 основного документа. Если вы хотите добавить импортированные страницы на разные страницы, вам необходимо создать объект canvas внутри цикла.

+0

спасибо для объяснения. Как я уже говорил, «pdfStamper.getUnderContent (страница, 0, 0);« Я не хочу добавлять целую страницу, но хочу добавить pdf-страницу в абсолютную позицию в существующем pdf. 'copy.addPage (copy.getImportedPage (reader, 1));' похоже на добавление всей страницы. исправь меня? –

+0

Из вашего предыдущего вопроса и комментариев, похоже, что вы хотите добавить всю страницу. Это также происходит, когда вы используете 'addTemplate()', не так ли? Нет метода 'getUnderContent()', который принимает 3 параметра. –

+0

'addTemplate (page, x, y)' имеет 'x' и' y' координаты. Я не могу использовать 'PdfCopy', если мне нужно разместить страницу в абсолютном положении в другом формате pdf, правильно? –