Подсчет количества вложений в PDF с использованием iText - PullRequest
0 голосов
/ 31 января 2019

Я пытаюсь подсчитать количество вложений в PDF-файле, чтобы проверить наш код вложения.Код, который у меня есть, работает большую часть времени, но в последнее время он начинает давать сбои, когда количество вложений увеличивается, а также размер вложений.Пример: у меня есть PDF-файл с 700 вложениями, общий объем которого составляет 1,6 ГБ.И еще один с 65 вложениями около 10 МБ.Счет 65 был сделан постепенно.Мы создали его файл за файлом.При 64 файлах (около 9,8 Мб) рутина считалась нормально.Добавьте файл 65 (около .5 МБ), и процедура не удалась.

Это на itextpdf-5.5.9.jar под jre1.8.0_162

Мы все еще тестируем различные комбинации номеров файлов иразмер, чтобы увидеть, где он ломается.

private static String CountFiles() throws IOException, DocumentException {

    Boolean errorFound = new Boolean(true);
    PdfDictionary root;
    PdfDictionary names;
    PdfDictionary embeddedFiles;
    PdfReader reader = null;
    String theResult = "unknown";

    try {
        if (!theBaseFile.toLowerCase().endsWith(".pdf"))
            theResult = "file not PDF";
        else {
            reader = new PdfReader(theBaseFile);
            root = reader.getCatalog();
            names = root.getAsDict(PdfName.NAMES);
            if (names == null)
                theResult = "0";
            else {
                embeddedFiles = names.getAsDict(PdfName.EMBEDDEDFILES);
                PdfArray namesArray = embeddedFiles.getAsArray(PdfName.NAMES);
                theResult = String.format("%d", namesArray.size() / 2);
            }
            reader.close();
            errorFound = false;
        }
    }
    catch (Exception e) {
        theResult = "unknown";
    }
    finally {
        if (reader != null)
            reader.close();
    }
    if (errorFound)
        sendError(theResult);
    return theResult;
}

private static String AttachFileInDir() throws IOException, DocumentException {

    String theResult = "unknown";
    String outputFile = theBaseFile.replaceFirst("(?i).pdf$", ".attach.pdf");
    int maxFiles = 1000;
    int fileCount = 1;

    PdfReader reader = null;
    PdfStamper stamper = null;

    try {
        if (!theBaseFile.toLowerCase().endsWith(".pdf"))
            theResult = "basefile not PDF";
        else if (theFileDir.length() == 0)
            theResult = "no attach directory";
        else if (!Files.isDirectory(Paths.get(theFileDir)))
            theResult = "invalid attach directory";
        else {
            reader = new PdfReader(theBaseFile);
            stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
            stamper.getWriter().setPdfVersion(PdfWriter.VERSION_1_7);
            Path dir = FileSystems.getDefault().getPath(theFileDir);
            DirectoryStream<Path> stream = Files.newDirectoryStream(dir);
            for (Path path : stream) {
                stamper.addFileAttachment(null, null, path.toFile().toString(), path.toFile().getName());
                if (++fileCount > maxFiles) {
                    theResult = "maxfiles exceeded";
                    break;
                }
            }
            stream.close();
            stamper.close();
            reader.close();
            theResult = "SUCCESS";
        }
    }
    catch (Exception e) {
        theResult = "unknown";
    }
    finally {
        if (stamper != null)
            stamper.close();
        if (reader != null)
            reader.close();
    }
    if (theResult != "SUCCESS")
        sendError(theResult);
    return theResult;
}

Я ожидаю простого подсчета вложений назад.Кажется, что происходит так, что namesArray возвращается null.Результат остается "неизвестным".Я подозреваю namesArray пытается удержать все файлы и задыхается от размера.

Примечание. Файлы прикрепляются с использованием процедуры AttachFileInDir.Сбросьте все файлы в каталог и запустите AttachFileInDir.И да, перехват ошибок в AttachFileInDir нуждается в работе.

Любая помощь приветствуется или приветствуется другой метод

1 Ответ

0 голосов
/ 02 февраля 2019

Я наконец получил это.Оказывается, каждый KID является словарем имен ...

Каждое ИМЯ содержит 64 ссылки на файлы.На 65 файлов и выше он составил словарь KIDS массив имен.Итак, 279 файлов = (8 * 64 +46) / 2 (всего 9 элементов массива KIDS).

Одна вещь, которую мне пришлось компенсировать.Если удалить все вложения из PDF-файла, он оставляет артефакты в отличие от PDF-файла, который никогда не имел вложения

private static String CountFiles() throws IOException, DocumentException {

    Boolean errorFound = new Boolean(true);
    int totalFiles = 0;
    PdfArray filesArray;
    PdfDictionary root;
    PdfDictionary names;
    PdfDictionary embeddedFiles;
    PdfReader reader = null;
    String theResult = "unknown";

    try {
        if (!theBaseFile.toLowerCase().endsWith(".pdf"))
            theResult = "file not PDF";
        else {
            reader = new PdfReader(theBaseFile);
            root = reader.getCatalog();
            names = root.getAsDict(PdfName.NAMES);
            if (names == null){
                theResult = "0";
                errorFound = false;
            }
            else {
                embeddedFiles = names.getAsDict(PdfName.EMBEDDEDFILES);
                filesArray = embeddedFiles.getAsArray(PdfName.NAMES);
                if (filesArray != null)
                    totalFiles = filesArray.size();
                else {
                    filesArray = embeddedFiles.getAsArray(PdfName.KIDS);
                    if (filesArray != null){
                        for (int i = 0; i < filesArray.size(); i++)
                            totalFiles += filesArray.getAsDict(i).getAsArray(PdfName.NAMES).size();                         
                    }
                }
                theResult = String.format("%d", totalFiles / 2);
                reader.close();
                errorFound = false;
            }
        }
    }
    catch (Exception e) {
        theResult = "unknown" + e.getMessage();
    }
    finally {
        if (reader != null)
            reader.close();
    }
    if (errorFound)
        sendError(theResult);
    return theResult;
}
...