Hallo zusammen,
ich versuche mich gerade an einem HTTP Download Manager. Den Code ohne JavaFX habe ich am laufen und nun versuche ich das Ganze in eine kleine JavaFX basierte GUI zu "gießen". Ich versuche hierbei das MVC Pattern zu benutzen, so wie ich es hier im Forum gelernt habe. Als Basis hatte ich dazu mal mit Hilfe von dzim eine kleine Muster Applikation geschrieben. Siehe Github MVC-Example
Ich habe verschieden Eingabefelder in meinem MainController:
Wenn alle erfoderlichen Felder ausgefüllt sind wird der Start Button aktiv. Beim click auf den Start Button wird dann folgende Methode im MainController ausgeführt:
Die Arbeit wird dann im ServiceWorkerTask1 gemacht - so meine Idee. Hier habe ich bis jetzt folgendes ausgeführt, was auch so funktioniert:
1. Ich erstelle den DownloadeFolder falls dieser nicht existiert. Das ganze mache ich in einem DAOService:
2. Dann ermiietel ich die Größe in Byte des zu ladenden Files:
Auch das funktioniert soweit.
Info: Der Code für den Proxy Server (CheckBox) ist noch nicht implementiert, aktuell wird immer proxy verwendet.
Nun fehlt mir noch folgendes:
- Start Download des Files
- In der ProgressBar soll angezeigt werden wieviel Bytes von Gesamt Bytes geladen sind.
- Am Ende soll noch noch der Durchsatz angezeigt werden, z.B.: 2 MByte/sec.
Der Code aus dem Programm *OHNE* JavaFX sieht dann so aus:
An dieser Stelle fehlt mir nun die Idee wie ich diesen Download und die Anzeige bzw. Update der ProgressBar in mein Programm, sprich in den ServiceTask am Besten integrieren kann. Folgendes ist mir im Detail nicht klar:
1. Wie kann ich den Download im Hintergrund laufen lassen. Meine Idee wäre hier den Download Code in den DAOService zu integrieren.
2. Wenn der Download im DAOService läuft habe ich dort keinen Zugriff auf das Model um z.B. die geladenen Bytes zu speichern um diese dann im MainController anzuzeigen und damit auch die ProgressBar zu bedienen.
3. Ich müsste dann ja auch noch einen Merker, bzw. Trigger (BooleanProperty im Model !!??) haben der mir zeigt das der Download nun fertig ist.
Ich hoffe ich habe mein Problem anschaulich erklärt und Ihr habe eine Idee wie ich das programmieren könnte.
Gruß
Ralf
ich versuche mich gerade an einem HTTP Download Manager. Den Code ohne JavaFX habe ich am laufen und nun versuche ich das Ganze in eine kleine JavaFX basierte GUI zu "gießen". Ich versuche hierbei das MVC Pattern zu benutzen, so wie ich es hier im Forum gelernt habe. Als Basis hatte ich dazu mal mit Hilfe von dzim eine kleine Muster Applikation geschrieben. Siehe Github MVC-Example
Ich habe verschieden Eingabefelder in meinem MainController:
Wenn alle erfoderlichen Felder ausgefüllt sind wird der Start Button aktiv. Beim click auf den Start Button wird dann folgende Methode im MainController ausgeführt:
Java:
public void startDownloadButtonTapped() {
// Clear messages TextArea/Labels before starting ...
messages.setText("");
message1Label.setText("");
message2Label.setText("");
toggleStartStopDownloadButton.setFadeTransitionShowButtonOne(false);
pBar.progressProperty().bind(serviceWorkerTask1.progressProperty());
downloadFolderTextField.setDisable(true);
sourceUrlTextField.setDisable(true);
proxyServerTextField.setDisable(true);
proxyServerTextField.setOpacity(0.25);
proxyPortTextField.setDisable(true);
proxyPortTextField.setOpacity(0.25);
model.setDownloadFinished(false);
if (!serviceWorkerTask1.isRunning()) {
LOGGER.info("Start downloading service task ...");
serviceWorkerTask1.reset();
serviceWorkerTask1.start();
}
}
Die Arbeit wird dann im ServiceWorkerTask1 gemacht - so meine Idee. Hier habe ich bis jetzt folgendes ausgeführt, was auch so funktioniert:
Java:
Service serviceWorkerTask1 = new Service() {
int indexValue;
@Override
protected Task createTask() {
return new Task() {
@Override
protected Void call() throws Exception {
// Start entering execution code here ...
// Check, and if necessary create DownloadFolder ...
dao.checkAndCreateDownloadFolder(downloadFolderTextField.getText());
// Get file size
model.setFileSize(dao.getFileSize(sourceUrlTextField.getText()));
if (model.getFileSize() != -1) {
Platform.runLater(() -> message2Label.setText("File size: " + model.getFileSize() + " Bytes"));
} else {
serviceWorkerTask1.onFailedProperty();
}
// final int max = 10;
// int counter;
// for (counter = 1; counter <= max; counter++) {
// indexValue = model.getArrayIndex(counter, max);
// updateMessage("Value at index " + counter + ": " + indexValue);
// updateProgress(counter, max);
// Thread.sleep(1000);
// }
// End entering execution code here ...
return null;
}
@Override
protected void succeeded() {
super.succeeded();
messages.appendText("Download Manager Task Succeeded!");
LOGGER.info("Download Manager Task Succeeded!");
updateProgress(1.0, 1.0);
toggleStartStopDownloadButton.setFadeTransitionShowButtonOne(true);
downloadFolderTextField.setDisable(false);
sourceUrlTextField.setDisable(false);
proxyServerTextField.setDisable(false);
proxyServerTextField.setOpacity(1.0);
proxyPortTextField.setDisable(false);
proxyPortTextField.setOpacity(1.0);
}
@Override
protected void cancelled() {
super.cancelled();
messages.appendText("Download Manager Task Cancelled!");
LOGGER.info("Download Manager Task Cancelled!");
toggleStartStopDownloadButton.setFadeTransitionShowButtonOne(true);
downloadFolderTextField.setDisable(false);
sourceUrlTextField.setDisable(false);
proxyServerTextField.setDisable(false);
proxyServerTextField.setOpacity(1.0);
proxyPortTextField.setDisable(false);
proxyPortTextField.setOpacity(1.0);
updateProgress(0, 0);
}
@Override
protected void failed() {
super.failed();
messages.appendText("Download Manager Task Failed!");
LOGGER.info("Download Manager Task Failed!");
toggleStartStopDownloadButton.setFadeTransitionShowButtonOne(true);
downloadFolderTextField.setDisable(false);
sourceUrlTextField.setDisable(false);
proxyServerTextField.setDisable(false);
proxyServerTextField.setOpacity(1.0);
proxyPortTextField.setDisable(false);
proxyPortTextField.setOpacity(1.0);
updateProgress(0, 0);
}
};
}
1. Ich erstelle den DownloadeFolder falls dieser nicht existiert. Das ganze mache ich in einem DAOService:
Java:
public void checkAndCreateDownloadFolder(String downloadFolder) {
try {
downloadFolderFile = new File(downloadFolder);
if (!downloadFolderFile.exists()) {
downloadFolderFile.mkdirs();
}
} catch (Exception ex) {
fireException(ex);
}
}
2. Dann ermiietel ich die Größe in Byte des zu ladenden Files:
Java:
public int getFileSize(String link) {
URLConnection conn = null;
try {
URL url = new URL(link);
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxyserver", 8080));
conn = url.openConnection(proxy);
if (conn instanceof HttpURLConnection) {
((HttpURLConnection) conn).setRequestMethod("HEAD");
}
conn.getInputStream();
return conn.getContentLength();
} catch (Exception ex) {
fireException(ex);
return -1;
} finally {
if (conn instanceof HttpURLConnection) {
((HttpURLConnection) conn).disconnect();
}
}
}
Auch das funktioniert soweit.
Info: Der Code für den Proxy Server (CheckBox) ist noch nicht implementiert, aktuell wird immer proxy verwendet.
Nun fehlt mir noch folgendes:
- Start Download des Files
- In der ProgressBar soll angezeigt werden wieviel Bytes von Gesamt Bytes geladen sind.
- Am Ende soll noch noch der Durchsatz angezeigt werden, z.B.: 2 MByte/sec.
Der Code aus dem Programm *OHNE* JavaFX sieht dann so aus:
Java:
public void run() {
try {
URL url = new URL(link);
HttpURLConnection hConnection = (HttpURLConnection) url.openConnection();
// Get size of file (int Bytes) to be downloaded ...
int fileSize = getFileSize(url);
// Inputstream arbeitet immer mit Byte
BufferedInputStream bufferedInputStream = new BufferedInputStream(hConnection.getInputStream());
// Datei schreiben / erstellen
outputFile = new File(defaultDownloadFolder, "DownloadFile.data");
OutputStream outputStream = new FileOutputStream(outputFile);
BufferedOutputStream bOutputStream = new BufferedOutputStream(outputStream, 1024);
byte[] buffer = new byte[1024];
int downloaded = 0;
int readByte = 0;
while ((readByte = bufferedInputStream.read(buffer, 0, 1024)) >= 0) {
bOutputStream.write(buffer, 0, readByte);
downloaded += readByte;
System.out.println("Bereits " + downloaded + " Byte " + " von " + fileSize + " Bytes geladen");
}
bOutputStream.close();
bufferedInputStream.close();
System.out.println("Download erfolgreich");
} catch (Exception e) {
e.printStackTrace();
}
}
An dieser Stelle fehlt mir nun die Idee wie ich diesen Download und die Anzeige bzw. Update der ProgressBar in mein Programm, sprich in den ServiceTask am Besten integrieren kann. Folgendes ist mir im Detail nicht klar:
1. Wie kann ich den Download im Hintergrund laufen lassen. Meine Idee wäre hier den Download Code in den DAOService zu integrieren.
2. Wenn der Download im DAOService läuft habe ich dort keinen Zugriff auf das Model um z.B. die geladenen Bytes zu speichern um diese dann im MainController anzuzeigen und damit auch die ProgressBar zu bedienen.
3. Ich müsste dann ja auch noch einen Merker, bzw. Trigger (BooleanProperty im Model !!??) haben der mir zeigt das der Download nun fertig ist.
Ich hoffe ich habe mein Problem anschaulich erklärt und Ihr habe eine Idee wie ich das programmieren könnte.
Gruß
Ralf
Zuletzt bearbeitet: