# Wie CSV Datei herunterladen?



## Refti (10. Feb 2012)

Hallo,

ich habe einen Link der folgendermaßen Aufgebaut ist: http:// .... /exportCSV

Rufe ich diesen im Browser auf, werde ich nach Username und Passwort gefragt. Nach Eingabe dieser, wird eine cvs generiert - es öffnet sich der "Datei speichern"-Dialog des Browsers.

Nun möchte ich den Link automatisiert aus Java heraus aufrufen und die CSV Datei speichern. Ich habe es mit folgendem Code versucht:


```
InputStreamReader isr = null;
BufferedReader br = null;
try {
  URLConnection con = new URL("http", "proxy", 8080, "http://.../exportCSV").openConnection();
  String encodedLogin = new sun.misc.BASE64Encoder().encode("username:passwort".getBytes());
  con.setRequestProperty("Authorization", "Basic " + encodedLogin);
  isr = new InputStreamReader(con.getInputStream(), "UTF-8");
  br = new BufferedReader(isr);
  while (br.ready()) {
    System.out.println(br.readLine());
  }
} catch (Exception e) {
  e.printStackTrace();
} finally {
  try { br.close(); } catch (Exception err) {}
}
```

Bis zum System.out läuft das Programm gar nicht erst, d.h. bei con.getInputStream geht's nicht weiter... (keine Exception)

Anmerkung:
Die Punkte (...) im Link sind natürlich nur im Forum-Beispielcode.
Username und Passwort sind natürlich durch die korrekten Werte ausgetauscht.


----------



## maki (10. Feb 2012)

AFAIK ist die Authorization ein header, k.A. was setRequestProperty macht.

Denke mit dem HttpClient wärst du besser dran.


----------



## madlion (10. Feb 2012)

Was mich dabei gerade wundert ist eine Parameter bei der URL.
Du gibst Protokoll, Host und Port als extra Parameter an und dann beim Parameter wieder "http://.../exportCSV". Das ist so nicht korrekt.
Entweder du machst

```
new URL("http://.../exportCSV")
```
oder

```
new URL("http", "proxy", 8080, "/exportCSV")
```

Dann sollte es klappen.

Du solltest die noch den http-errorcode und ggf. die message ausgeben. Damit du z.B. feststellen kannst wenn deine Anmweldung fehlgeschlagen ist.
Irgendwie so in der Art.


```
httpURLConnection.connect();

int responseCode = httpURLConnection.getResponseCode();
String responseMessage = httpURLConnection.getResponseMessage();

if (LOG.isDebugEnabled()) {
	LOG.debug("responseCode      : " + responseCode);
	LOG.debug("responseMessage : " + responseMessage);
}

if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
//...
}
```


----------



## madlion (10. Feb 2012)

maki hat gesagt.:


> AFAIK ist die Authorization ein header, k.A. was setRequestProperty macht.


Korrekt, und setRequestProperty macht genau das.

Für das einfache Runterladen einer Datei muß man nicht unbedingt den HttpClient verwenden und damit "eine" zusätzliche Jar einbinden.


----------



## maki (10. Feb 2012)

madlion hat gesagt.:


> Für das einfache Runterladen einer Datei muß man nicht unbedingt den HttpClient verwenden und damit "eine" zusätzliche Jar einbinden.


Kommt darauf an, zB. ob man mit sun.misc.* Klassen besser dran ist 
IMHO nicht, jars einbinden gehört IME zum täglich Brot bei Java.


----------



## Refti (10. Feb 2012)

Mein gepostetes Beispiel funktioniert mit einer nicht geschützten Datei einwandfrei. An der Adresse mit oder ohne http liegt es nicht.

Denke das Problem ist die Authentifizierung. Es poppt kein Dialog auf (bei manuellem Aufruf), sondern eine allgemeine Einstiegsseite mit User + Passwort, auf die man -denke ich- geforwarded wird.


----------



## madlion (10. Feb 2012)

maki hat gesagt.:


> Kommt darauf an, zB. ob man mit sun.misc.* Klassen besser dran ist


Stimmt, da hast du recht. Das sollte man natürlich eigentlich auch nicht machen.



maki hat gesagt.:


> IMHO nicht, jars einbinden gehört IME zum täglich Brot bei Java.


Das stimmt schon aber man mußt auch nicht unnötig Jars einbinden, wenn es nicht notwendig ist. Vorallem nicht bei nem trivialen Http-Request.

@Refti Heißt das es kommt eine Html-Seite in der du Username und Passwort eingeben mußt?

Dann klappt die Basic-Authentication natürlich nicht. Das ist ein Form-Based Login.
Dann nimmst du am besten den HttpClient (wie Maki schon vorgeschlagen hat) und machst nen Post Request.
Du mußt dir dir Login Seite mal anschauen. Dort wird eine Form sein mit den Parametern für Username und Passwort und die URL an die der Post Request gehen muß.


----------



## Andi_CH (10. Feb 2012)

Hm - einfach einmal laut denken --- wenn es bullshit ist, bitte ich um Weiterbildung ;-)

Erst login, dann Zugriff - da wird beim Filerequest kaum mehr Username und Passwort mitgeschickt. Ich denke da liegt dann ein Cookie auf deinem Rechner (Ich werde des öfteren aus Webseiten ausgeloggt, wenn ich Cookies lösche)

Wie der eigentliche Zugriff aussieht weiss ich nicht - vielleicht musst du das per sniffer herausfinden und wirst 2 Requests abschicken müssen - erst der Login (Der dir dasCookie liefert) und dann den Filerequest.


----------



## ARadauer (10. Feb 2012)

Es kommt einfach drauf an was das für ein LogIn ist, apache über htaccess oder irgend ein php formular... zeig mal die ganze url


----------



## madlion (10. Feb 2012)

@Andi_CH "Erst login, dann Zugriff" Im Prinzip schon.

Der Browser weiß ja erstmal nicht ob ein Seite geschützt ist oder nicht. Also wird versucht die Seite aufzurufen und der Server prüft ob man Authentifiziert ist und meldet dem Browser ggf. daß nicht.
Und heir kommt es nun darauf an wie geschützt wurde.
Wird Http Basic-Authentication verwendet liefert der Server im Response Header den Http-Code 401. Der Browser zeigt darauf hin ein Logindialog an.
Die Daten (Username, Passwort) werden dann im Http-Header übertragen.
Ich weiß jetzt nicht genau wie es in den einzelnen Browsern implementiert ist aber es gibt Clients die schicken die Daten bei jedem Request mit.
Das Ganze hat erstmal nichts mit Cookies zu tun.

Und dann gibt es noch das ganze Thema Form-Based Login. Da liefert der Server eine Html-Seite zur Eingabe der Logindaten an den Browser. Der Browser schickt die Anwort per POST-Request dann den Server zurück.

Danach hat man meist ein Cookie mit einer Session Id damit der Server einen wiedererkennt.


----------



## Refti (10. Feb 2012)

Das ganze scheint Form basiert zu sein:

<form name=pdlogin method="post" action="/pkmslogin.form">
...
<td><input name="username">
...
<input type="password" name="password" size="15" onkeypress="javascript:if(event.keyCode && event.keyCode == 13) 
"	{document.pdlogin.submit()"
</tr>
</table>
<INPUT TYPE="HIDDEN" NAME="login-form-type" VALUE="pwd"></TD>
</FORM>


----------



## ARadauer (10. Feb 2012)

ja dann macht 
con.setRequestProperty("Authorization", "Basic " + encodedLogin);
natürlich null sinn

versucht mal die werte über get mitzugeben, das wird wahrscheinlich nicht klappen. Dann musst du die werte mit post übergeben


----------



## Refti (10. Feb 2012)

Ich werd's mit post versuchen und mir erstmal in Ruhe den apache httpclient anschauen. Danke erstmal für eure Hilfe!


----------



## madlion (10. Feb 2012)

Ok, also wie vermutet Form-Based Login.
Und mit kommt der Inhalt recht bekannt vor. Das sieht nach einem IBM Produkt aus.

Ich denke es müßte in etwar wie folgt aussehen:

```
HttpPost httppost = new HttpPost("http://.../pkmslogin.form");

StringBody usernameBody= new StringBody(username);
StringBody passwordBody = new StringBody(password);
StringBody formTypeBody = new StringBody("pwd");

MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("username", usernameBody);
reqEntity.addPart("password", passwordBody );
reqEntity.addPart("login-form-type", formTypeBody );

httppost.setEntity(reqEntity);

HttpResponse response = httpclient.execute(httppost);
```
Ich habe den Code allerdings nicht getestet, daher bin ich mir nicht genau sicher ob es do geht.


----------

