abdullah affoura
abdullah affoura

Reputation: 25

how to bind JFX ProgressBar with my link in java

I am trying to make a java program download an app from my server by getting download link from it with this code :

private void downloadFile(String link) throws Exception {

URL url = new URL(link);

URLConnection conn = url.openConnection();

InputStream is = conn.getInputStream();

int max = conn.getContentLength();

pane.setText(pane.getText()+"\n"+"Downloding files...\nUpdate Size : "+(max/1000000)+" Mb");

BufferedOutputStream fOut = new BufferedOutputStream(new FileOutputStream(new 
   File("update.zip")));
byte[] buffer = new byte[32 * 1024];

int bytesRead = 0;

int in = 0;

while ((bytesRead = is.read(buffer)) != -1) {

    in += bytesRead;

    fOut.write(buffer, 0, bytesRead);
}
fOut.flush();

fOut.close();

is.close();

pane.setText(pane.getText()+"\nDownload Completed Successfully!");

and it is working fine ... I did search about how to bind my progress bar to this download link but I couldnt figure it out .... I would appreciate any kind of help.

Upvotes: 0

Views: 48

Answers (1)

VGR
VGR

Reputation: 44328

Create a Task and perform your download in that Task’s call method:

String link = /* ... */;

File downloadsDir = new File(System.getProperty("user.home"), "Downloads");
downloadsDir.mkdir();

File file = File(downloadsDir, "update.zip");

Task<Void> downloader = new Task<Void>() {
    @Override
    public Void call()
    throws IOException {
        URL url = new URL(link);
        URLConnection conn = url.openConnection();

        long max = conn.getContentLengthLong();

        updateMessage(
            "Downloading files...\nUpdate Size : " + (max/1000000) + " MB");

        try (InputStream is = conn.getInputStream();
             BufferedOutputStream fOut = new BufferedOutputStream(
                new FileOutputStream(file))) {

            byte[] buffer = new byte[32 * 1024];

            int bytesRead = 0;
            long in = 0;
            while ((bytesRead = is.read(buffer)) != -1) {
                in += bytesRead;
                fOut.write(buffer, 0, bytesRead);
                updateProgress(in, max);
            }
        }

        updateMessage("Download Completed Successfully!");

        return null;
    }
};

Notice the use of the inherited methods updateProgress and updateMessage.

Then you can simply bind the ProgressBar’s properties to your Task’s properties.

progressBar.progressProperty().bind(downloader.progressProperty());

And you can even monitor the Task’s message as it changes:

downloader.messageProperty().addListener(
    (o, oldMessage, newMessage) -> pane.appendText("\n" + newMessage));

You’ll probably want to let the user know if the download fails. You can do this with the Task’s onFailed property:

downloader.setOnFailed(e -> {
    Exception exception = downloader.getException();

    StringWriter stackTrace = new StringWriter();
    exception.printStackTrace(new PrintWriter(stackTrace));

    TextArea stackTraceField = new TextArea(stackTrace.toString());
    stackTraceField.setEditable(false);

    Alert alert = new Alert(Alert.AlertType.ERROR);
    alert.initOwner(pane.getScene().getWindow());
    alert.setTitle("Download Failure");
    alert.setHeaderText("Download Failed");
    alert.setContextText(
        "Failed to download " + link + ":\n\n" + exception);
    alert.getDialogPane().setExpandableContent(stackTraceField);
    alert.show();
});

Task implements Runnable, so you can start it by passing it to any standard multithreading class:

new Thread(downloader, "Downloading " + link).start();

Or:

CompletableFuture.runAsync(downloader);

Or:

ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(downloader);

Upvotes: 1

Related Questions