PDFBox PDFMergerUtility在JavaFX应用程序上不稳定

时间:2018-07-06 06:45:32

标签: java javafx pdfbox

我的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还是因为错过了关键性的事情?

1 个答案:

答案 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文件。