Мое приложение 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, возможно, из-за того, что я использовал Задачу снаружи или из-за того, что я пропустил что-то важное?