Downloadobjekt schließt nicht ab

Jungspund

Mitglied
Hallo,
ich habe folgendes Problem :
ich habe in Java ein Download-Objekt welches byteweise eine Datei von einen Server kopiert.
das ganze Funkioniert auch zu 99,9%, nur der Download schließt nicht ab, sprich er bleibt bei 100-700 KB vor der Beendigung stehen und wertet den Download als beendet. Ich finde dabei absolut keinen Lösungsansatz.

hier der Code für das Objekt:

Java:
	public void run() {

		RandomAccessFile file = null;
		InputStream stream = null;

		try {

			// Open connection to URL.
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();

			// Specify what portion of file to download.
			connection.setRequestProperty("Range", "bytes=" + downloaded + "-");

			// Connect to server.
			connection.connect();
			if (debug) {
				System.out.println(connection.getURL().toString());
				System.out.println("\n-\n" + connection.getPermission());
				System.out.println("\n-\n" + connection.getResponseCode());
				System.out.println("\n-\n" + connection.getContentLength());
			}

			// Make sure response code is in the 200 range.
			if (connection.getResponseCode() / 100 != 2) {
				throw new Exception(this.name + " - code is not in the 200 range");
			}
			;

			// Check for valid content length.
			int contentLength = connection.getContentLength();
			if (contentLength < 1) {
				throw new Exception(connection.getContentLength() + "not a valid content length");
			}

			/*
			 * Set the size for this download if it hasn't been already set.
			 */
			if (size == -1) {
				size = contentLength;
				stateChanged();
			}

			// Open file and seek to the end of it.

			file = new RandomAccessFile(this.pfad + "/" + this.name + ".zip", "rw");

			file.seek(downloaded);
			this.file = file;

			stream = connection.getInputStream();
			while (status == DOWNLOADING) {
				//System.out.println("downloading");
                                /*
				 * Size buffer according to how much of the file is left to
				 * download.
				 */
                                if((size-downloaded) <= 0) {
                                  break;  
                                } 
				byte buffer[];
				if (size - downloaded > MAX_BUFFER_SIZE) {
					buffer = new byte[MAX_BUFFER_SIZE];
				} else{
					buffer = new byte[size - downloaded];
                                }
                                System.out.println("-------------------------------------");
                                System.out.println("Status         : " + status);
                                System.out.println("Size            : " + size);
                                System.out.println("downloaded : " + downloaded);
                                System.out.println("difference    : " + (size - downloaded));
                                System.out.println("Buffer          : " + buffer.length);
                                System.out.println("-------------------------------------");
				// Read from server into buffer.
				int read = stream.read(buffer);
				if (read == -1)
					break;

                                // Write buffer to file.
				if (new File(this.pfad + "/" + this.name + ".zip").exists()) {
					file.write(buffer, 0, read);
					downloaded += read;
				}
				stateChanged();
			}

			/*
			 * Change status to complete if this point was reached because
			 * downloading has finished.
			 */
			if (status == DOWNLOADING) {
				status = COMPLETE;
                                System.out.println("finished");
				//log.write2log(new String[] { "Download", "Fertig: download = " + this.name + " nach " + this.pfad +                              //"abgeschlossen.", this.name });
				stateChanged();
			}
		} catch (Exception e) {
			error(e);
			if (debug) {
				e.printStackTrace();
			}
		} finally {
			// Close file.
			if (file != null) {
				try {
					file.close();
				} catch (Exception e) {
					if (debug) {
						e.printStackTrace();
					}
				}
			}

			// Close connection to server.
			if (stream != null) {
				try {
					stream.close();
				} catch (Exception e) {
					error(e);
					if (debug) {
						e.printStackTrace();
					}
				}
			}
		}

	}

Dabei lass ich mir immer die gedownloadete Größe, die Insgesammte Größe, die Differenz, den Status und die länge des byte Arrays ausgeben.

Dabei geschieht es jedoch, dass ich auch auf solche Ausgaben stoße:
Code:
----------------------------
Status     : 2
Size       : 99785855
downloaded : 99787791
difference : -1936
Buffer     : 1024
----------------------------
zur näheren Erläuterung:
STATUS 0 = downloading
1 = paused
2 = complete
3 = cancelled
4 = error
 
Das Problem scheint wohl zu sein, dass er die Schleife schneller durchläuft, als er das Objekt wirklich downloaded. Sprich wenn ich den Download pausiere, und der Status auf 1 gesetzt wird,
setzt die While-Schleife trotzdem ihren Vorgang ca 7-10 mal fort, obwohl dort eine Abfrage auf Status == 0 besteht und der System.out.println(status) mir auch den Status 1 wiedergibt(pausiert).
Gibt es irgendeine Möglichkeit die einen Delay in der Schleife zu verhindern, oder einen Grund warum dieser überhaupt auftreten kann? Das ganze Projekt arbeitet übrigens mit JSP und AJAX, bei welchen auch teilweise Verzögerungen von bis zu 3 sec auftreten, nach dem post
 
Ein Detail:
Code:
                byte buffer[];
                if (size - downloaded > MAX_BUFFER_SIZE) {
                    buffer = new byte[MAX_BUFFER_SIZE];
 ...
Hat das einen bestimmten Grund? Weil, die Länge des Buffers müsste man IMO auch ausserhalb des Scopes der while-Schleife definieren können. Auch wenn der Buffer 1024 lang ist, es aber nur noch 2 bytes gibt, so wird er die einfach in die 0te und 1te Stelle laden, du bekommst ja über die read-Methode die Anzahl gelesenen bytes zurück.

Ein weiteres Detail (es lässt sich natürlich tagelang darüber streiten,...):
Code:
if (read == -1)
                    break;
mach doch
Code:
if(read == -1){
  status = COMPLETED;
}else if (new File(this.pfad + "/" + this.name + ".zip").exists()) {
  file.write(buffer, 0, read);
  downloaded += read;
}
... wenn du doch schon eine while-Bedingung hast,...


Sprich wenn ich den Download pausiere, und der Status auf 1 gesetzt wird,
setzt die While-Schleife trotzdem ihren Vorgang ca 7-10 mal fort, obwohl dort eine Abfrage auf Status == 0 besteht und der System.out.println(status) mir auch den Status 1 wiedergibt(pausiert).
Wahrscheinlich setzt du diesen Status aus einem anderen Thread raus? Je nach Anwendungsfall kann man da entweder Thread.yield() aufrufen, damit der Thread von der CPU runtergeht, oder aber, das ist glaub ich, die korrektere Variante, das Feld status als volatile definieren. So zwingt man den Thread, den Wert des Feldes jedesmal aus dem Speicher zu laden.

Gruss
slowy
 
Zuletzt bearbeitet:
Zurück