HTTP Zugriff auf http-Server - Error 400

Andi_CH

Top Contributor
Ich habe einen Server am laufen der mir ein Bild einer Webcam liefert.
Der Zugriff mit dem Browser über den Link
Code:
http://servername:8081/?action=snapshot
geht

Der aus einem klugen Buch abgetippte und modifizerte Code liefert "Error 400"

Java:
URL url = new URL("http://servername:8081/");
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
PrintWriter out = new PrintWriter(connection.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
out.print("action=snapshot");
out.close();
String line;
while((line=in.readLine()) != null) {
	System.out.println(line);
}

Was mach der Browser anders?
 
Das muss so sein, denn:

Java:
URL url = new URL("http://vakserver:8081/?action=snapshot");
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
PrintWriter out = new PrintWriter(connection.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
out.close();
String line;
while((line=in.readLine()) != null) {
	System.out.println(line);
}

Code:
java.io.IOException: Server returned HTTP response code: 400 for URL: http://vakserver:8081/?action=snapshot
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at ch.mbh.vak.client.GetPicture.main(GetPicture.java:23)
 
Habe ich zu wenig präzise gefragt? Wie macht man es richtig?

Mein erster Versuch (siehe unten) brachte dasselbe Resultat:
(dieser Code läuft in anderem Zusammenhang)

Java:
/**
 * Sends a message to the given web host and site and receives its respond
 * @param pHost the host name
 * @param pSite The site
 * @param pMessage The message string
 * @param pTimeout the connection timeout (sec)
 * @return the response from the web server
 * @throws Exception if the message could not send to the host
 */
public static Map<String, String> sendHttpPost(String pHost, int pPort, String pSite, String pMessage, int pTimeout, boolean pDebug) throws Exception {
	System.out.println("sendHttpPost() host = " + pHost + ", port = " + pPort + ", site = " + pSite + ", message = " + pMessage);
	Socket socket = null;
	OutputStream out = null;

	byte[] theMessage = null;
	try  {
		theMessage = pMessage.getBytes("UTF-8");
		StringBuffer msgBuffer = new StringBuffer();
		msgBuffer.append("POST");
		msgBuffer.append(" " + pSite + " ");
		msgBuffer.append("HTTP/1.1");
		msgBuffer.append("\r\n");
		msgBuffer.append("Host: ");
		msgBuffer.append(pHost);
		msgBuffer.append("\r\n");
		msgBuffer.append("Content-type: ");
		msgBuffer.append("application/x-www-form-urlencoded");
		msgBuffer.append("\r\n");
		msgBuffer.append("Content-length: ");
		msgBuffer.append(String.valueOf(theMessage.length));
		msgBuffer.append("\r\n");
		msgBuffer.append("\r\n");
		msgBuffer.append(pMessage);

		if (pDebug) {
			System.out.println("==========================================");
			System.out.println("AHttpPost.sendHttpPost() send = " + msgBuffer.toString());
		}
		byte[] message = msgBuffer.toString().getBytes("UTF-8");
		// write datas to the host 'pHost' on pPort
		if (pTimeout == 0) {
			pTimeout = CONNECTION_TIMEOUT;
		}
		socket = new Socket(pHost, pPort);
		socket.setSoTimeout(1000 * pTimeout);              //set socket timeout (ms)
		out = socket.getOutputStream();
		out.write(message);
		out.flush();
		//
		// read answer if any	 
		InputStream inputStream = socket.getInputStream();
		InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
		BufferedReader br = new BufferedReader(inputStreamReader);

		Map<String, String> response = new HashMap<String, String>();
		String line = null;
		boolean ok = false;
		while ((line = br.readLine()) != null) {
			if (pDebug)
				System.out.println("AHttpPost.sendHttpPost() response = " + line);
			if (line.indexOf(RESPONSE_OK_ID) >= 0) {
				ok = true;
				break;
			}
			//split the response into a key/value pair
			String[] keyValue = line.split("=");
			if (keyValue.length == 2) {
				response.put(keyValue[0], keyValue[1]);
			}
		}
		if (ok) {
			return response;
		} else {
			String errMsg = " Internal server error " + pHost;
			//show the last line from the server
			if (line != null) {
				errMsg += "\n" + line;
			}
			throw new Exception(errMsg);
		}
	} catch(UnknownHostException uhex) {
		throw new Exception("Keine Verbindung zu " + uhex.getMessage());
	} catch(ConnectException cex) {
		throw new Exception("Keine Verbindung zu " + cex.getMessage());
	} catch(SocketTimeoutException tex) {
		throw new Exception(tex.getMessage());
	} catch (IOException ioex) {
		throw ioex;
	} catch (Exception ex) {
		throw ex;
	} finally {
		try {
			socket.close();
			out.close();
		} catch (Exception ioex) {}
	}
}

Output:
Code:
sendHttpPost() host = servername, port = 8081, site = /?action=snapshot, message = 
==========================================
AHttpPost.sendHttpPost() send = POST /?action=snapshot HTTP/1.1
Host: servername
Content-type: application/x-www-form-urlencoded
Content-length: 0


AHttpPost.sendHttpPost() response = HTTP/1.0 400 Bad Request
AHttpPost.sendHttpPost() response = Content-type: text/plain
AHttpPost.sendHttpPost() response = Connection: close
AHttpPost.sendHttpPost() response = Server: MJPG-Streamer/0.2
AHttpPost.sendHttpPost() response = Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0
AHttpPost.sendHttpPost() response = Pragma: no-cache
AHttpPost.sendHttpPost() response = Expires: Mon, 3 Jan 2000 12:34:56 GMT
AHttpPost.sendHttpPost() response = 
AHttpPost.sendHttpPost() response = 400: Not Found!
AHttpPost.sendHttpPost() response = Malformed HTTP request
 
Kannst ja mal mit Firebug nachsehen was der Browser so alles mitschickt, vielleicht ist HttpClient doch besser geeignet als URLConnection.

Warum der HTTP Sever 400 zurückgibt lässt sich so leider nicht sagen, entscheidet ja der Server was er zurückschickt, schreibt er denn ein log?
 
Mach mal in Deinem Minibeispiel kein [c]setDoOutput(true)[/c] (das lange Beispiel habe ich mir jetzt nicht angesehen). Dadurch signalisierst Du, dass noch etwas kommt und die Anfrage wird als POST und nicht als GET durchgeführt.
 
Java:
URL url = new URL("http://servername:8081/?action=snapshot");
URLConnection connection = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while((line=in.readLine()) != null) {
	System.out.println(line);
}

Output:
ÿØÿÛ..... (¢€ ¢euË¥ (¢€ (¢€

Das könnte möglicherweise das Bild sein -> wie bastle ich nun daraus ein Bild?

(Das muss aber ein Teures sein, so oft wie €, ¢, £, $ und ¥ drin vorkommen 😀 )
 
Java:
Das könnte möglicherweise das Bild sein -> wie bastle ich nun daraus ein Bild?[/QUOTE]
Ich nehme an das Bild soll angezeigt werden, ohne es vorher auf die Platte zu schreiben?
Grundsätzlich würde ich die Daten nicht mit einem Reader sondern mit einen InputStream (z.B. DataInputStream) einlesen, da ein Reader für Textstreams gedacht ist und m.W. die Daten direkt interpretiert.
(Zum Testen, ob es ich bei den Daten um ein Bild handelt würde ich diese aber dennoch erst einmal auf die Platte schreiben.)
Die eingelesenen Daten könnte man versuchen in ein byte-Array zu lesen und dieses dann mittels ByteArrayInputstrem und ImageIO.read(...) als Image einzulesen.
Eventuell gibt es auch die Möglichkeit direkt vom InputStream der URLConnection in ein Image einzulesen. Hab sowas aber noch nie gemacht. Ich habe eigentlich immer die Daten in eine Datei auf Platte geschrieben und dann von der Datei geladen.
 
Eigentlich genau umgekehrt - es reicht mir völlig wenn es als File vorhanden ist.

Mir ist schon nicht klar warum der InputStream einem InputStreamReader übergeben werden muss und der wiederum einem Buffered Reader ... Ich bin erst auf dem Niveau angelangt auf dem ich finde, dass Java alles unnötig kompliziert macht :bahnhof: 😉

"Könnte man versuchen" - WEISS wer wie es geht? (Nö - es ist keine Hausaufgabe zu der ich die Lösung erschleichen will - ich möchte nur schneller zu einem Ziel kommen, als wenn ich erst alle Fehler selbst machen und 100 Seiten API übersetzen muss) ;-)

Java:
URL url = new URL("http://" + pServerName + ":" + pPort + "/?action=snapshot");
URLConnection connection = url.openConnection();
Map<String, List<String>>  list = connection.getHeaderFields();
System.out.println("=== Headerfields ===");
for (String s : list.keySet()) {
	System.out.println(" " + s + " : " + list.get(s));
}

Code:
=== Headerfields ===
 null : [HTTP/1.0 200 OK]
 Content-type : [image/jpeg]
 Expires : [Mon, 3 Jan 2000 12:34:56 GMT]
 Connection : [close]
 Server : [MJPG-Streamer/0.2]
 Cache-Control : [no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0]
 Pragma : [no-cache]

(Spannend finde ich "null" auf der ersten Zeile - es gibt als einen Key der null ist ???:L )
Sieht aber schon vielversprechend aus ...
 
Zuletzt bearbeitet:
Eigentlich genau umgekehrt - es reicht mir völlig wenn es als File vorhanden ist.
Wenn es sich bei den Daten tatsächlich um ein Bild handelt.Dann könnte man ja den InputStream der URLConnection direkt auslesen in byte-Arrays auslesen und diese per FileOutputStream auf die Platte schreiben.
Java:
InputStream in = connection.getInputStream();
byte[] buffer=new byte[1024];
FileOutputStream fileOut = new FileOutputStream(new File("c:\\bild.jpg"));
int len;
while ((len = in.read(buffer))>0)
      fileOut.write( buffer, 0, len ); 
fileOut.close();
 

Neue Themen


Zurück
Oben