Binärdaten mit dem Servlet senden
Um Binärdaten zu senden, muss lediglich der passende Typ im Content-Type eingestellt sein. Dabei kann es sich um Daten handeln, die der Browser interpretiert oder auch nicht.
Beispiel Content-Type bei Bildern:
response.setContentType( "image/jpeg" ); response.setContentType( "image/gif" );
Wenn wir den Inhaltstyp – wie oben geschehen – setzen und einen binären Datenstrom mit den Bildinformationen verschicken, ist schnell ein Bilder-Servlet geschrieben:
package com.tutego.servlet;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class BinarySender extends HttpServlet
{
public void doGet( HttpServletRequest request,
HttpServletResponse response )
throws ServletException, IOException
{
String filename = "C:/WINNT/Profiles/Administrator/"+
"Desktop/wirelessduke.jpg";
InputStream in = new BufferedInputStream(
new FileInputStream(filename) );
String s = URLConnection.guessContentTypeFromStream(in);
response.setContentType( s );
byte[] pic = new byte[ in.available() ];
in.read( pic );
in.close();
OutputStream out = response.getOutputStream();
out.write( pic );
}
}
In den Eingabestrom schreiben wir dieses Mal keine Unicode-Zeichen, sondern binäre Daten. Daher ist ein Writer nicht nötig. Stattdessen holen wir uns direkt einen OutputStream mit getOutputStream(). Falls wir uns jedoch schon vorher einen Writer mit getWriter() geholt haben, bestraft uns Tomcat mit einer netten Seite und dem Fehler 500: Writer und Stream dürfen nicht gleichzeitig offen sein.
Beherzigen wir dies, können wir einfach mit write() Daten schreiben, und der Client versucht, diese zu interpretieren. Der Content-Type und die Binärdaten müssen zusammenpassen, andernfalls ist das Verhalten nicht immer vorhersehbar.
Falls uns der Datentyp selbst nicht klar ist, lässt sich eine kaum bekannte statische Funktion aus der Klasse URLConnection nutzen: guessContentTypeFromStream(). Sie versucht mit Hilfe der ersten Bytes auf den Inhalt zu schließen. Da die Methode einen Stream mit mark/reset benötigt (damit die Daten gelesen und wieder zurückgesetzt werden können), geben wir ihm einen markierungsfähigen Datenstrom in Form des BufferedInputStream. Findet er den Typ (wenn nicht, liefert die Methode null), wird dieser sofort in setContentType() eingesetzt. Somit können wir die Datei leicht ändern, und die Klasse sucht sich automatisch den richtigen Typ für verbreitete Binärdaten. Unter der Servlet-API gibt es auch die Methode ServletContext.getMimeType(), die das Erkennen des Typs vornimmt.