То, что вы наблюдали в этом и в вашем предыдущем вопросе, связано с особенностью класса iText PdfDocument
: хотя он представляет документ PDF, он не хранит все его в памятиили в каком-то доступном хранилище. В частности, если вы добавляете к нему контент, этот новый контент по умолчанию выгружается из памяти в PdfWriter
как можно скорее, делая его недоступным для PdfDocument
.
Это позволяет вам сохранитьобъем памяти довольно низкий при создании больших PDF-файлов с помощью iText, что может быть очень актуально в приложениях с высокой пропускной способностью.
Недостатком является то, что существуют ограничения на использование экземпляров PdfDocument
;в частности, вы не можете свободно копировать из экземпляров, которые были записаны, поскольку текущее состояние копируемых данных может больше не быть доступным.
Чтобы предотвратить копирование противоречивых данных, iText запрещает копирование из PdfDocument
экземпляров. куда можно записать, т. е. которые имеют PdfWriter
.
Таким образом,
- , если вы хотите скопировать из aдокумент,
PdfDocument
необходимо инициализировать без a PdfWriter
; - , если вы хотите (нетривиально) изменить документ,
PdfDocument
необходимо инициализировать с a PdfWriter
; - , поэтому, если вы хотите изменить и скопировать из документ, вы не можете использоватьодин и тот же
PdfDocument
экземпляр для обоих действий!
Поэтому для вашего случая использования вы должны
- либо взять вывод
PdfDocument
с PdfWriter
после применения изменений и использования его в качестве ввода PdfDocument
без PdfWriter
для копирования с; - или открытия двух отдельных
PdfDocument
экземпляры из исходного файла, один с и один без PdfWriter
, и применить изменения к первому и скопировать со второго.
Первый вариант необходим, если данные, которые выхочу скопировать должен содержать изменения, которые вы применяете. Последнее необходимо, если они не содержат их. Если вам все равно, или если вы знаете, что на скопированные данные не влияют изменения, любой из этих вариантов подходит.
В вашем случае вы копируете все страницы из всех документов в pdfDocuments
в целевой документ, поэтому, в частности, вы хотите, чтобы внесенные изменения также были скопированы в целевой документ. Таким образом, применяется первый вариант, вам нужно взять вывод PdfDocument
с PdfWriter
после применения изменений и использовать его в качестве ввода PdfDocument
без PdfWriter
для копирования.
Вы можете сделать это, изменив addBlankPage
следующим образом:
public PdfDocument addBlankPage(final MediaModel pdfDocument) throws IOException {
try ( InputStream inputStream = mediaService.getStreamFromMedia(pdfDocument);
PdfReader reader = new PdfReader(inputStream);
PdfWriter writer = new PdfWriter(pdfDocument.getRealFileName());
PdfDocument document = new PdfDocument(reader, writer)) {
document.addNewPage(document.getFirstPage().getPageSize());
}
return new PdfDocument(new PdfReader(pdfDocument.getRealFileName()));
}
или если вы на самом деле не хотите записывать PDF-файл в файловую систему:
public PdfDocument addBlankPage(final MediaModel pdfDocument) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try ( InputStream inputStream = mediaService.getStreamFromMedia(pdfDocument);
PdfReader reader = new PdfReader(inputStream);
PdfWriter writer = new PdfWriter(baos);
PdfDocument document = new PdfDocument(reader, writer)) {
document.addNewPage(document.getFirstPage().getPageSize());
}
return new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())));
}