# Downloaden einer Datei geht nicht?



## Ikaron (28. Nov 2011)

Hallo, ich versuch eine Datei herunterzuladen. Das geht zwar, aber wenn ich vorher das timeout umstelle, geht es nicht mehr. Bei Standarttimeout geht es, dieses ist aber null und man kann null nicht als Property setzen, weil man sonst eine nullPointerException bekommt. Ein leerer String ("") geht auch nicht. Wie krieg ich das jetzt hin? Ich hab auch schon versucht die default Properties zu speichern und dann einzusetzen, gibt aber immer nocht den Fehler. Hier ist mein Code:

```
public void downloadFile(String url, String outputPath) {

	try {
			
		HttpURLConnection connection = (HttpURLConnection) new URL(url)
			.openConnection();

		connection.connect();
		int size = connection.getContentLength();

		File file = new File(outputPath);
		FileOutputStream fout = new FileOutputStream(file);
		InputStream stream = connection.getInputStream();

		int downloaded = 0;

		while (true) {

			byte buffer[];

			buffer = new byte[size];

			int read = stream.read(buffer);
			if (read == -1)
				break;

			fout.write(buffer, 0, read);

			downloaded += read;

			System.out.println((downloaded / size) + "% (" + downloaded
				+ "/" + size + ")");
		}

		fout.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
}
```

Error:

```
java.net.SocketTimeoutException: Read timed out
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection$6.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.net.www.protocol.http.HttpURLConnection.getChainedException(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at downloadFile(Codebeispiel:13)
Caused by: java.net.SocketTimeoutException: Read timed out
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.io.BufferedInputStream.fill(Unknown Source)
	at java.io.BufferedInputStream.read1(Unknown Source)
	at java.io.BufferedInputStream.read(Unknown Source)
	at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
	at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getHeaderField(Unknown Source)
	at java.net.URLConnection.getHeaderFieldInt(Unknown Source)
	at java.net.URLConnection.getContentLength(Unknown Source)
	at downloadFile(Codebeispiel:8)
	... 1 more
```


----------



## Dit_ (28. Nov 2011)

shau dir die Zeile #13 genauer an, ich glaube da ist der Fehler.


----------



## eRaaaa (28. Nov 2011)

Mit dieser Beschreibung des Problems kann doch niemand etwas anfangen. 1-2 komplette Sätze und evtl. Codebeispiel oder zumindest Nennung der verwnedeten Klassen/Bibliotheken könnte schon weiterhelfen....


----------



## Ikaron (28. Nov 2011)

Dit_ hat gesagt.:


> shau dir die Zeile #13 genauer an, ich glaube da ist der Fehler.



Zeile 13 von was?



eRaaaa hat gesagt.:


> Mit dieser Beschreibung des Problems kann doch niemand etwas anfangen. 1-2 komplette Sätze und evtl. Codebeispiel oder zumindest Nennung der verwnedeten Klassen/Bibliotheken könnte schon weiterhelfen....



Ich hab ein bisschen was hinzugefügt.


----------



## Dit_ (28. Nov 2011)

Also ich mache das so:


```
URL url = new URL(urlFrom.replace(" ", "%20"));
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.connect();
            int responseCode = conn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                File targetFile = new File(outputPath);
                FileOutputStream os = new FileOutputStream(targetFile);
                byte buffer[] = new byte[BUFFER_SIZE];
                InputStream is = conn.getInputStream();
                int count = 0;
                long loaded = 0;
                /*
                 * SPEICHERN.
                 */
                while ((count = is.read(buffer)) > 0) {
                    os.write(buffer, 0, count);
                    os.flush();
                }
                os.close();
            }
```

und habe eigentlich keine Probleme mit download.


----------



## Ikaron (29. Nov 2011)

Wie gesagt, meine Download-Methode geht ja, aber NUR, wenn das timeout vorher nicht gesetzt wurde. Ich teste mal, ob's vllt daran liegt, dass es ein Bild ist.
Edit: Jop, liegt am timeout. Wenn ich das nicht setze, geht aber auch nix, da die Überprüfung blockiert.


----------



## Andi_CH (30. Nov 2011)

Die im Eingangspost gezeigte Methode läuft - wo ist das Problem? Wurde die in der Zwischenzeit geändert (was ich offen gesagt doof finden würde)

Nur die sysout-Zeile solltest du noch ändern

1.0 damit der Quotient präziser wird und * 100 damit es wirklich % gibt ;-)


```
System.out.println((downloaded*1.0 / size)*100 + "% (" + downloaded + "/" + size + ")");
```


----------



## Ikaron (30. Nov 2011)

Andi_CH hat gesagt.:


> Die im Eingangspost gezeigte Methode läuft - wo ist das Problem? Wurde die in der Zwischenzeit geändert (was ich offen gesagt doof finden würde)
> 
> Nur die sysout-Zeile solltest du noch ändern
> 
> ...



Die Prozentanzeige hab ich schon verbessert, nur vergessen es zu posten. Die Methode läuft NICHT, wenn man vorher das Timeout setzt. Das heißt ich habe eine "exists" Methode geschrieben, welche aber ein Timeout benötigt. Dadurch geht der Download nicht mehr.


----------



## Michael... (30. Nov 2011)

Dein Problem ist, dass zuvor - aus welchen Gründen auch immer - ein Read Timeout gesetzt wurde?
Warum setzt Du es in der Methode nicht einfach hoch auf z.B. 60000ms?

Ansonsten weiss ich nicht ob es so geschickt ist den Buffer zum einlesen auf die Dateigröße zu setzen. Bei kleinen Dateien ist das kein Poblem, aber was ist wenn sie mal ein bißchen größer ist? Da könnte man schnell mal den Rahmen des zur Verfügung stehenden Heap Spaces sprengen!!

Grundsätzlich würde ich die Schleife auch ein bisschen kompakter gestalten.Üblich ist z.B.

```
int downloaded = 0;
	int read;
	byte[] buffer = new byte[100000];
	while ((read = stream.read(buffer)) != -1) {
		fout.write(buffer, 0, read);
		downloaded += read;
		System.out.printf("%.1f%% ( %d / %d )\n", (downloaded * 100.0 / size), downloaded, size);
	}
	...
```


----------



## Ikaron (30. Nov 2011)

Michael... hat gesagt.:


> Dein Problem ist, dass zuvor - aus welchen Gründen auch immer - ein Read Timeout gesetzt wurde?
> Warum setzt Du es in der Methode nicht einfach hoch auf z.B. 60000ms?
> 
> Ansonsten weiss ich nicht ob es so geschickt ist den Buffer zum einlesen auf die Dateigröße zu setzen. Bei kleinen Dateien ist das kein Poblem, aber was ist wenn sie mal ein bißchen größer ist? Da könnte man schnell mal den Rahmen des zur Verfügung stehenden Heap Spaces sprengen!!
> ...


Danke für die kleinere Download-Schleife. Ich hab schon das Timeout von zwischen 200ms bis 1000000000ms gesetzt, kein Unterschied, fliegt immer nach ner halben Sekunde, warum auch immer.


----------



## Michael... (30. Nov 2011)

Ikaron hat gesagt.:


> Danke für die kleinere Download-Schleife. Ich hab schon das Timeout von zwischen 200ms bis 1000000000ms gesetzt, kein Unterschied, fliegt immer nach ner halben Sekunde, warum auch immer.


ne halbe Stunde, wenn ich die Nullen sollte das durchzähle sollte das für mehr als eine halbe Stunde reichen. Wie groß ist denn die Datei und wie schaut es während dessen mit der Ausgabe des Fortschritts aus?


----------



## Ikaron (30. Nov 2011)

Michael... hat gesagt.:


> ne halbe Stunde, wenn ich die Nullen sollte das durchzähle sollte das für mehr als eine halbe Stunde reichen. Wie groß ist denn die Datei und wie schaut es während dessen mit der Ausgabe des Fortschritts aus?



Kommt nicht bis zum Downloaden, fliegt beim ImputStream raus wegen "ReadTimedOut". Wie gesagt, wenn ich vorher keinen "exists" check mache (Welcher ein Timeout setzt) geht es perfekt. Die Datei is geschätzte 4kB.


----------



## Michael... (30. Nov 2011)

Um das mal zusammen zu fassen hier mal dein "exists" und der Download in einem.
Und bei Dir kommt folgender Code nicht einmal bis zu 
	
	
	
	





```
System.out.println("found");
```
 in Zeile 10, wenn Du die Kommentierung in Zeile 6 nicht entfernst?
Bei mir funktioniert der Code ohne Probleme:

```
public static void main(String[] args) {
		try {
			String url = "http://1.1.1.5/bmi/www.java-forum.org/images/misc/java_forum_org.gif";
			String outputPath = "C:/temp/test.gif";
			// System.getProperties().setProperty("sun.net.client.defaultConnectTimeout", "35");
			// System.getProperties().setProperty("sun.net.client.defaultReadTimeout", "35");
			HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
			con.setRequestMethod("HEAD");
			if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
				System.out.println("found");
				HttpURLConnection con2 = (HttpURLConnection) new URL(url).openConnection();
				con2.connect();

				FileOutputStream fout = new FileOutputStream(new File(outputPath));
				InputStream stream = con2.getInputStream();

				int downloaded = 0;
				int size = con2.getContentLength();
				int read;
				byte[] buffer = new byte[100000];
				while ((read = stream.read(buffer)) != -1) {
					fout.write(buffer, 0, read);
					downloaded += read;
					System.out.printf("%.1f%% ( %d / %d )\n", (downloaded * 100.0 / size), downloaded, size);
				}
				fout.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
```


----------



## Ikaron (1. Dez 2011)

Michael... hat gesagt.:


> Um das mal zusammen zu fassen hier mal dein "exists" und der Download in einem.
> Und bei Dir kommt folgender Code nicht einmal bis zu
> 
> 
> ...



Richtig, wenn ich die Kommentare als Code einsetze geht nix mehr. Als Kommentar geht aber das "exists" nicht, da er ewig wartet bevor er false returnt.


----------



## Michael... (1. Dez 2011)

Sorry. Selbst wenn ich in folgendem Code die Erhöhung des Timeouts in Zeile 10 auskommentiert läuft es bei mir auf unterschiedlichen Systemen ohne Probleme durch.

```
try {
		String url = "http://www.java-forum.org/images/misc/java_forum_org.gif";
		String outputPath = "C:/temp/test.gif";
		//System.getProperties().setProperty("sun.net.client.defaultConnectTimeout", "500");
		System.getProperties().setProperty("sun.net.client.defaultReadTimeout", "500");
		HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
		con.setRequestMethod("HEAD");
		if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
			System.out.println("found");
			System.getProperties().setProperty("sun.net.client.defaultReadTimeout", "50000");
			HttpURLConnection con2 = (HttpURLConnection) new URL(url).openConnection();
			con2.connect();

			FileOutputStream fout = new FileOutputStream(new File(outputPath));
			InputStream stream = con2.getInputStream();

			int downloaded = 0;
			int size = con2.getContentLength();
			int read;
			byte[] buffer = new byte[100000];
			while ((read = stream.read(buffer)) != -1) {
				fout.write(buffer, 0, read);
				downloaded += read;
				System.out.printf("%.1f%% ( %d / %d )\n", (downloaded * 100.0 / size), downloaded, size);
			}
			fout.close();
		}
		else
			System.out.println("HTTP Respone: " + con.getResponseCode());
	} catch (Exception e) {
		e.printStackTrace();
	}
```


----------



## Ikaron (1. Dez 2011)

. Jetzt geht's bei mir auch, warum auch immer. Vielen Dank! Okey, doch nicht, zu früh gefreut. Wieder Read Timed out.


----------



## Ikaron (2. Dez 2011)

Michael... hat gesagt.:


> Sorry. Selbst wenn ich in folgendem Code die Erhöhung des Timeouts in Zeile 10 auskommentiert läuft es bei mir auf unterschiedlichen Systemen ohne Probleme durch.
> 
> ```
> try {
> ...



Wenn das Bild aber NICHT existiert, und man DANACH versucht ein existierendes zu downloaden, geht es nicht.


----------

