我的JavaFX应用程序正在从服务器下载PDF,如果PDF是横向的,则旋转为纵向,然后将所有PDF文件合并为一个PDF文件以打印出来。
一切正常,除了程序会随机停留在输出合并的PDF或将其中一个PDF文件添加到PDFMergerUtility(我正在使用PDFBox 2.0.11并尝试了2.0.9)之外。因为我的应用程序需要一个ProgressBar和TextArea来显示当前的动作或状态,所以我在控制器页面中使用了一个任务。程序挂起时,它没有输入任何异常或打印任何消息,但完全停止了后台操作。我尝试了少量文件(<50个文件)和大型文件测试(> 1000),但是它们的绝对正常或随机挂起的结果相同。
下面是我的控制器程序的代码:
public class ReadDataPageController implements Initializable {
public long startTime;
public long stopTime;
@FXML
private Button btnNext, btnCancel, btnPrevious;
@FXML
private Label infoLabel, time, total;
@FXML
private ProgressBar progBar;
@FXML
private TextArea textArea;
public Task<String> dlTask() {
return new Task<String>() {
@Override
protected String call() throws Exception {
DownloadUtil dlutil = new DownloadUtil();
StringBuilder textStr = new StringBuilder();
List<String> dlList = mainApp.DL_LIST;
// Download PDF files from FTP
super.updateValue(textStr.append("Preparing files for download...\n").toString());
for (int count = 0; count < dlList.size(); count++) {
String PDFLink = dlList.get(count).getPDFLink();
super.updateTitle("Downloading file" + PDFLink + " ...");
super.updateValue(textStr.append("Got " + PDFLink + "\n").toString());
try {
dlutil.exec(PDFLink);
// downloaded location will be stored inside List DownloadUtil.pdfList
} catch (IndexOutOfBoundsException ex) {
super.updateValue(textStr.append("Link not found for " + PDFLink + "\n").toString());
} catch (Exception ex) {
super.updateValue(textStr.append("Error while downloading " + PDFLink + " :" + ex.getMessage() + "\n").toString());
}
super.updateProgress(count + 1, dlList.size() * 3);
}
super.updateProgress(dlList.size(), dlList.size() * 3);
super.updateTitle("Download action has finished.");
super.updateValue(textStr.append("Download action has finished.\n").toString());
// Rotate downloaded PDFs
super.updateTitle("Preparing files for PDF rotation...");
super.updateValue(textStr.append("Preparing files for PDF rotation...\n").toString());
for (int i = 0; i < dlutil.pdfList.size(); i++) {
try {
String fileName = dlutil.pdfList.get(i);
rotatePDF(new File(fileName));
super.updateValue(textStr.append("Rotating PDF ("+(i+1)+" of "+dlutil.pdfList.size()+")...\n").toString());
} catch (Exception ex) {
super.updateValue(textStr.append("Error:" + ex.getMessage() + "...\n").toString());
ex.printStackTrace();
}
super.updateProgress(dlutil.pdfList.size() + i + 1, dlutil.pdfList.size() * 3);
}
if (PRINT_OPTION == PrintType.PRINT) {
// Merge downloaded PDFs
super.updateValue(textStr.append("Preparing files for PDF merging action...\n").toString());
PDFMergerUtility pdfutil = new PDFMergerUtility();
for (int i = 0; i < dlutil.pdfList.size(); i++) {
try {
String fileName = dlutil.pdfList.get(i);
pdfutil.addSource(fileName);
super.updateTitle("Adding files (" + (i + 1) + "/" + dlutil.pdfList.size() + ")");
} catch (Exception ex) {
super.updateValue(textStr.append("Error:" + ex.getMessage() + "...\n").toString());
ex.printStackTrace();
}
super.updateProgress(dlutil.pdfList.size()*2 + i + 1, dlutil.pdfList.size() * 3);
}
// Output merged pdf
try {
pdfutil.setDestinationFileName("../odt/merge.pdf");
pdfutil.mergeDocuments();
} catch (Exception ex) {
ex.printStackTrace();
}
super.updateTitle("Merged all PDFs.");
}
super.updateProgress(100, 100);
super.updateTitle("All action has been finished.");
super.updateValue(textStr.append("All action has been finished, press Next to choose your printing option.\n").toString());
return textStr.toString();
}
};
}
/**
* Rotates PDF images 90 degree if the PDF is portrait
* @param resource the PDF file path
* @throws InvalidPasswordException
* @throws IOException
*/
public void rotatePDF(File resource) throws InvalidPasswordException, IOException {
try {
PDDocument document = PDDocument.load(resource);
int pageCount = document.getNumberOfPages();
System.out.println("Reading file: "+resource+", total page="+pageCount);
for (int i = 0; i < pageCount; i++) {
PDPage page = document.getDocumentCatalog().getPages().get(i);
PDPageContentStream cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND,
false, false);
Matrix matrix = Matrix.getRotateInstance(Math.toRadians(90), 0, 0);
cs.transform(matrix);
cs.close();
PDRectangle cropBox = page.getCropBox();
if (cropBox.getWidth() > cropBox.getHeight()) {
System.out.println("ROTATE "+i+"th");
Rectangle rectangle = cropBox.transform(matrix).getBounds();
PDRectangle newBox = new PDRectangle((float) rectangle.getX(), (float) rectangle.getY(),
(float) rectangle.getWidth(), (float) rectangle.getHeight());
page.setCropBox(newBox);
page.setMediaBox(newBox);
document.save(resource);
}
}
document.close();
} catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
}
}
是否有任何可能导致PDFMergerUtility不稳定的原因,可能是因为我在外面使用了Task还是因为错过了关键性的事情?
答案 0 :(得分:2)
宾果!例外是OutOfMemoryError,而JavaFX的Task使它保持沉默。
我在启动任务时添加了以下代码,它将处理异常:
task.setOnFailed(new EventHandler<WorkerStateEvent>(){
@Override
public void handle(WorkerStateEvent event) {
Throwable th = task.getException();
System.out.println("Error on Task:"+th.getMessage());
th.printStackTrace();
}
});
为避免OutOfMemoryError,我将合并作业分成100个页面(每个合并作业),并另存为多个合并的PDF文件。