0

I have written a piece of code for downloading a file from internet (in background service) and showing the progress of download in a popup stage. The code compiles successfully and there is no runtime error. However no download takes place and progress indicator remains indeterminate.

The code is tailored for illustrating my point. Please have a look at it and let me understand where I have gone wrong.

Thanks!

public class ExampleService extends Application {
URL url;    
Stage stage;

public void start(Stage stage)
{
    this.stage = stage;
    stage.setTitle("Hello World!");
    stage.setScene(new Scene(new StackPane(addButton()), 400, 200));
    stage.show();
}

private Button addButton()
{
    Button downloadButton = new Button("Download");
    downloadButton.setOnAction(new EventHandler<ActionEvent>()
    {
        public void handle(ActionEvent e)
        {
           FileChooser fileSaver = new FileChooser();
            fileSaver.getExtensionFilters().add(new FileChooser.ExtensionFilter("PDF", "pdf"));                

            File file = fileSaver.showSaveDialog(stage);

            getDownloadService(file).start();               
        }
    });        
    return downloadButton;
}

private Service getDownloadService(File file)
{
   Service downloadService = new Service() 
   {
       protected Task createTask()
       {
           return doDownload(file);
       }
   };

   return downloadService;
}

private Task doDownload(File file)
{
    Task downloadTask = new Task<Void>()
    {
       protected Void call() throws Exception
        {
            url = new URL("http://www.daoudisamir.com/references/vs_ebooks/html5_css3.pdf");

            // I have used this url for this context only
            org.apache.commons.io.FileUtils.copyURLToFile(url, file); 

            return null;
        } 
    };
    showPopup(downloadTask);
    return downloadTask;
}

Popup showPopup(Task downloadTask)
{
    ProgressIndicator progressIndicator = new ProgressIndicator();
    progressIndicator.progressProperty().bind(downloadTask.progressProperty());

    Popup progressPop = new Popup();
    progressPop.getContent().add(progressIndicator);
    progressPop.show(stage);

    return progressPop;

    // I have left out function to remove popup for simplicity
}
public static void main(String[] args)
{
    launch(args);
}}
Mukesh P
  • 23
  • 6
  • If there were an exception, you would not know about it. Register an `onFailed` handler with the task: `downloadTask.setOnFailed(e -> downloadTask.getException().printStackTrace());`. If you want the progress to change, you need to call [`updateProgress(...)`](http://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html#updateProgress-long-long-) from your `call()` method. – James_D Mar 01 '17 at 16:51

2 Answers2

1

The line:

org.apache.commons.io.FileUtils.copyURLToFile(url, file);

...doesn't provide you any information about the progress of your download (there is no callback or any other indication of its progress). It just downloads something without giving you feedback.

You will have to use something else that gives you feedback on the progress.

Take a look at this questions answers for solutions with feedback (it is for Swing, but you should be able to adapt them for JavaFX): Java getting download progress

Community
  • 1
  • 1
john16384
  • 7,800
  • 2
  • 30
  • 44
  • I have looked at your link. I will have to figure out how to adapt the code to JavaFX. The code uses Java.io whereas I want to use org.apache.commons.io. which is simpler to use. – Mukesh P Mar 01 '17 at 18:45
0

You bind the ProgressIndicator's progress property to the Task's progress property, so that changes in the latter will be reflected in the former. However you never actually update your Task's progress.

If you want the progress indicator to show something, you're going to have to call updateProgress(workDone, max) within your task's body (or elsewhere). And that might be tricky if the download logic you're using doesn't give you any progress callbacks. (You could, perhaps, spawn a thread to repeatedly check the size of the file on the filesystem and use that as your current workDone; but you'd need to know what the eventual/complete size of the file would be in order to turn this into a percentage, which may or may not be easy.)

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • I understand using updateProgress() and finding eventual file size can be tricky. That is why I need more concrete response. All browsers implement this functionality. – Mukesh P Mar 01 '17 at 18:51