Слияние тегов PDF без разрушения тегов
Я пытаюсь объединить два файла PDF с тегами с файлом версии iTextPDF 5.4.4. После выполнения всех операций при закрытии документа на строке: document.close();): . Выкидывает ошибку ниже
java.lang.NullPointerException
PDF Creation Failed java.lang.NullPointerException
[B@1d5c1d5c
at com.itextpdf.text.pdf.PdfCopy.fixTaggedStructure(PdfCopy.java:878)
at com.itextpdf.text.pdf.PdfCopy.flushTaggedObjects(PdfCopy.java:799)
at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:836)
at com.itextpdf.text.Document.close(Document.java:416)
at PDFMerger.mergePDF(PDFMerger.java:189)
Пожалуйста, дайте мне знать, что может быть причиной этой проблемы.
Ниже приведен код, который я использую.
PdfReader reader = new PdfReader(pdf);
boolean setTagged=reader.isTagged() ;
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream("Merged.pdf"));
copy.setTagged();
document.open();
int n;
n = reader.getNumberOfPages();
for (int page = 0; page < n; ) {
copy.addPage(copy.getImportedPage(reader, ++page,true));
}
copy.freeReader(reader);
document.close();
reader.close();
2 ответа
Это похоже на ошибку в текущих версиях iText.
@ Бруно, может быть, кто-то должен посмотреть на это
PdfCopy
есть метод fixTaggedStructure
который пытается исправить помеченную структуру, которая была несколько искажена при копировании помеченных страниц. До текущего iText 5.4.6-SNAPSHOT включительно вы найдете следующий код
PdfDictionary dict = (PdfDictionary)iobj.object;
PdfIndirectReference pg = (PdfIndirectReference)dict.get(PdfName.PG);
//if pg is real page - do nothing, else set correct pg and remove first MCID if exists
if (!pageReferences.contains(pg) && !pg.equals(currPage)){
dict.put(PdfName.PG, currPage);
PdfArray kids = dict.getAsArray(PdfName.K);
if (kids != null) {
PdfObject firstKid = kids.getDirectObject(0);
if (firstKid.isNumber()) kids.remove(0);
}
}
для тегового элемента StructElem dict
из некоторого массива. Этот код неявно предполагает наличие записи для ключа PdfName.PG
в этом словаре dict
при выполнении pg.equals(currPage)
, К сожалению, эта запись является необязательной, например, образец документа, предоставленный OP, содержит такие словари StructElem, на которые ссылаются из некоторого массива без записи Pg. Это вызывает вопрос NPE.
В этом случае достаточно изменить порядок в equals
звоните, т.е. вместо
if (!pageReferences.contains(pg) && !pg.equals(currPage)){
надо использовать
if (!pageReferences.contains(pg) && !currPage.equals(pg)){
или же
if (pg != null && !pageReferences.contains(pg) && !pg.equals(currPage)){
в зависимости от фактической логики программы здесь.
@ Bruno Пожалуйста, проверьте, какой вариант является семантически правильным; В конце концов, я не очень люблю эту структуру с тегами...
Кодекс был написан на C#
public static byte[] mergeTest(byte[] pdf) {
PdfReader reader = null;
Document doc = null;
PdfCopy copy = null;
MemoryStream stream = new MemoryStream();
byte[] output = null;
try {
reader = new PdfReader(pdf);
doc = new Document();
copy = new PdfCopy(doc, stream);
bool tagged = reader.IsTagged();
if (tagged)
copy.SetTagged();
doc.Open();
for (int x = 1; x <= reader.NumberOfPages; x++) {
copy.AddPage(copy.GetImportedPage(reader, x, tagged));
}
copy.FreeReader(reader);
doc.Close();
copy.Close();
output = stream.ToArray();
stream.Flush();
stream.Dispose();
} catch (Exception ex) {
} finally {
try {
if (reader != null)
reader.Close();
} catch (Exception) { }
}
return output;
}