Извлечь портфолио PDF с большим количеством PDF в нем
У меня есть портфолио PDF с папками, подпапками и файлами. Мне нужно извлечь ту же структуру, используя iText в Java. Я не могу извлечь портфолио PDF с большим количеством PDF-файлов в нем. С небольшим количеством PDF не работает нормально.
Пожалуйста, найдите код, который я использую.
public void extractPortfolio(String src) {
PdfReader reader = new PdfReader(src);
PdfDictionary root = reader.getCatalog();
PdfDictionary names = root.getAsDict(PdfName.NAMES);
System.out.println("****names names *********" + names.getKeys().toString());
PdfDictionary embedded = names.getAsDict(PdfName.EMBEDDEDFILES);
System.out.println("####embedded embedded ########" + embedded.toString());
PdfArray filespecs =null;
filespecs=embedded.getAsArray(PdfName.NAMES);//all pdfs null in case of large no of pdfs
for (int i = 0; i < filespecs.size();) {
try {
extractAttachment(reader, folders, folder, filespecs.getAsString(i++), filespecs.getAsDict(i++));
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected void extractAttachment(PdfReader reader, Map<Integer, File> dirs, File dir, PdfString name, PdfDictionary filespec) throws IOException {
PRStream stream;
FileOutputStream fos;
String filename;
PdfDictionary refs = filespec.getAsDict(PdfName.EF);
File dirHere = dir;
String nameString = name.toUnicodeString();
if (nameString.startsWith("<")) {
int closing = nameString.indexOf('>');
if (closing > 0) {
int folderId = Integer.parseInt(nameString.substring(1, closing));
File folderFile = dirs.get(folderId);
System.out.println("Folder Fiel>>>"+folderFile.getName());
if (folderFile != null) {
dirHere = folderFile;
}
}
}
for (PdfName key : refs.getKeys()) {
stream = (PRStream) PdfReader.getPdfObject(refs.getAsIndirectObject(key));
filename = filespec.getAsString(key).toString();
fos = new FileOutputStream(new File(dirHere, filename));
fos.write(PdfReader.getStreamBytes(stream));
fos.flush();
fos.close();
}
}
В коде значение переменной filespecs равно нулю.
1 ответ
Проблема в том, что ваш код (который может быть основан на ответе, который я дал) предполагает, что (Каталог) -> Имена -> EmbeddedFiles немедленно содержит массив Имен с записями Filespec:
PdfDictionary names = root.getAsDict(PdfName.NAMES);
System.out.println("****names names *********" + names.getKeys().toString());
PdfDictionary embedded = names.getAsDict(PdfName.EMBEDDEDFILES);
System.out.println("####embedded embedded ########" + embedded.toString());
PdfArray filespecs =null;
filespecs=embedded.getAsArray(PdfName.NAMES);//all pdfs null in case of large no of pdfs
Это предположение неверно. (Каталог) -> Имена -> EmbeddedFiles является корнем так называемого дерева имен, и в качестве дерева оно может иметь детей, у которых снова могут быть собственные дети и т. Д., Что в конечном итоге приводит к конечному узлу, содержащему массив имен с записями Filespec.
Если у вас есть PDF с очень небольшим количеством вложений, обычно его дерево имен EmbeddedFiles несколько сжато, его корень также является единственным листовым узлом, и это ситуация, которую понимает ваш код и код из моего предыдущего ответа.
Таким образом, ваш код должен быть улучшен для повторения здесь, не только для поиска Имен во EmbeddedFiles, но и для Детей, а внутри них также не только для Имен, но также для Детей и т. Д. И т. Д.