Java PDFBox将锁定JPEG输入文件,直到应用程序退出
我在Windows7环境中使用PDFBox RC2,Java 1.8_66。我用它从一组200dpi的页面大小的图像文件(包括JPEG和PNG)中创建了一个PDF 事实证明,将JPEG文件添加到PDF时,PDImageXObject.createFromFile()例程无法关闭内部文件句柄,从而在应用程序的生命周期内锁定图像文件。将PNG文件添加到PDF时,没有问题 下面是一些重现该问题的示例代码。使用process explorer(从sysinternals),查看java.exe进程的打开文件句柄并运行此代码。我的测试使用了大约20个完整大小的JPEG文件。请注意,在方法退出后,仍有几个锁定的文件保留在后面Java PDFBox将锁定JPEG输入文件,直到应用程序退出,java,pdf,pdfbox,filelock,Java,Pdf,Pdfbox,Filelock,我在Windows7环境中使用PDFBox RC2,Java 1.8_66。我用它从一组200dpi的页面大小的图像文件(包括JPEG和PNG)中创建了一个PDF 事实证明,将JPEG文件添加到PDF时,PDImageXObject.createFromFile()例程无法关闭内部文件句柄,从而在应用程序的生命周期内锁定图像文件。将PNG文件添加到PDF时,没有问题 下面是一些重现该问题的示例代码。使用process explorer(从sysinternals),查看java.exe进程的打开
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;
}
作为一种解决方法,我回顾了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;
}
实际上,关闭
fis
不需要等待太长时间,因为JPEGFactory.createFromStream(doc,fis)
已经将整个流读取到字节[]
。在PDFBOX-3199中修复。谢谢你找到这个bug。顺便说一句,目前的版本是RC3。(它也有这个bug)。谢谢@TilmanHausherr!期待修复!它是固定的。您可以通过使用快照来使用修复,请参阅