JavaFX - File download with URL in textfield with save option

Viewed 60

I have a textfield in which a user can copy a URL. For example let's say: https://filesamples.com/samples/document/txt/sample3.txt

When the user presses Enter, he should get a window where he can specify the destination where this file should be saved. The file is a zip or txt file. A DirectoryChooser is the first thing that comes to mind, but I don't know how to combine this with a file download.

Thanks for the help.

EDIT:

Now hopefully I added a reproducible example. The code is from youtube, because I had trouble with the download function. In the textfield a user can copy the link above (https://filesamples.com/samples/document/txt/sample3.txt) and press enter. Now the file is in the project folder. But how do I implement a DirectoryChooser so that the user can choose where to safe the file?

Main:

package application;
    
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("fxml.fxml"));

            Scene scene = new Scene(root,800,800);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Controller:

package application;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;

public class Controller implements Initializable{

    @FXML
    private TextField textFieldDownload;
    
    @FXML
    private AnchorPane anchorPane;
    
    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        textFieldDownload.setOnAction(event -> {        
            Task<Void> task = new DownloadTask(textFieldDownload.getText());
            ProgressBar progressBar = new ProgressBar();
            progressBar.setPrefWidth(350);
            progressBar.progressProperty().bind(task.progressProperty());
            anchorPane.getChildren().add(progressBar);
            Thread thread = new Thread(task);
            thread.setDaemon(true);
            thread.start();
        });
    }
}

DownloadTask:

package application;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Paths;

import javafx.concurrent.Task;

public class DownloadTask extends Task<Void>{
    
    private String url;
    
    public DownloadTask(String url) {
        this.url = url;
    }

    @Override
    protected Void call() throws Exception {
        //String url = "https://filesamples.com/samples/document/txt/sample3.txt";
        
        String fileExtension = url.substring(url.lastIndexOf("."), url.length());
        
        URLConnection connection = new URL(url).openConnection();
        long fileLength = connection.getContentLengthLong();
        
        try(InputStream is = connection.getInputStream(); OutputStream os = Files.newOutputStream(Paths.get("test" + fileExtension))){
            long nread = 0L;
            byte[] buf = new byte[8192];
            int n;
            while ((n = is.read(buf)) > 0) {
                os.write(buf, 0, n);
                nread += n;
                updateProgress(nread, fileLength);
            }
        }
        return null;
    }
    
    @Override
    protected void failed() {
        System.out.println("failed");
    }
    
    @Override
    protected void succeeded() {
        System.out.println("downloaded");
    }
}
0 Answers
Related