PDFBox блокирует входной файл JPEG до выхода из приложения

Я использую PDFBox RC2 в среде Windows 7, Java 1.8_66. Я использую его для создания PDF-файла из коллекции файлов изображений размером 200 точек на дюйм, как JPEG, так и PNG.

Оказывается, что при добавлении файлов JPEG в PDF, подпрограмме PDImageXObject.createFromFile() не удается закрыть дескриптор внутреннего файла, таким образом блокируя файл изображения на время существования приложения. При добавлении файлов PNG в PDF проблем нет.

Вот пример кода, который воспроизводит проблему. Используя проводник процессов (из sysinternals), просмотрите дескрипторы открытых файлов для процесса java.exe и запустите этот код. Мой тест использует около 20 полноразмерных файлов JPEG. Обратите внимание, что после выхода из метода несколько заблокированных файлов все еще остаются позади.

public Boolean CreateFromImages_Broken(String pdfFilename, String[] imageFilenames) {

    PDDocument doc = new PDDocument();        
    for (String imageFilename : imageFilenames) {

        try {
            PDPage page = new PDPage();
            doc.addPage(page);

            PDImageXObject pdImage = PDImageXObject.createFromFile(imageFilename, doc);

            // at this point, if the imageFilename is a jpeg, pdImage holds onto a handle for 
            // the given imageFilename and that file remains locked until the application is closed

            try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
                float scale = (float)72.0 / 200;
                page.setMediaBox(new PDRectangle((int)(pdImage.getWidth() * scale), (int)(pdImage.getHeight() * scale)));
                contentStream.drawImage(pdImage, 0, 0, pdImage.getWidth()*scale, pdImage.getHeight()*scale);
            }
        } catch (IOException ioe) {
            return false;
        }                          
    }

    try {
        doc.save(pdfFilename);
        doc.close();                  
    } catch (IOException ex) {
        return false;
    }

    return true;
} 

1 ответ

В качестве обходного пути я рассмотрел исходный код для обработки PNG и JPEG, и мне удалось реализовать его, что, похоже, работает для обоих типов файлов:

public Boolean CreateFromImages_FIXED(String pdfFilename, String[] imageFilenames) {

    PDDocument doc = new PDDocument();        
    for (String imageFilename : imageFilenames) {

        FileInputStream fis = null;

        try {
            PDPage page = new PDPage();
            doc.addPage(page);

            PDImageXObject pdImage = null;

            // work around JPEG issue by opening up our own stream, with which
            // we can close ourselves instead of PDFBOX leaking it. For PNG
            // images, the createFromFile seems to be OK
            if (imageFilename.toLowerCase().endsWith(".jpg")) {
                fis = new FileInputStream(new File(imageFilename));
                pdImage = JPEGFactory.createFromStream(doc, fis);
            } else {
                pdImage = PDImageXObject.createFromFile(imageFilename, doc);
            }

            try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
                float scale = (float)72.0 / 200;
                page.setMediaBox(new PDRectangle((int)(pdImage.getWidth() * scale), (int)(pdImage.getHeight() * scale)));
                contentStream.drawImage(pdImage, 0, 0, pdImage.getWidth()*scale, pdImage.getHeight()*scale);                    

                if (fis != null) {
                    fis.close();
                    fis = null;
                }                    
            }

        } catch (IOException ioe) {
            return false;
        }                          
    }

    try {
        doc.save(pdfFilename);
        doc.close();                  
    } catch (IOException ex) {
        return false;
    }

    return true;        
}
Другие вопросы по тегам