#

Download JSPs

In vielen Beispielen wird darauf eingegangen, wie man mit einem Servlet binary content Downloads streamen kann. Das ganze geht auch per JSP.
Obwohl das ganze recht trivial ist, hier ein paar wichtige Details, die sehr hilfreich sind.

Um Binary Content durch ein Servlet oder JSP zu Streamen, sollte man neben den Binärdaten auch folgende Informationen über die Datei parat haben: Dateiname sowie Mime / Content Type.

Daher gehe ich von einem Objekt aus, welches in der folgenden Klasse gekapselt ist:

public interface BinaryObject{
  public String getName();
  public String getMimeType();
  public byte[] getContent();
}

Gefüllt werden kann ein solches Objekt durch die Dateiattribute eines File-Objektes, oder durch die Spalten einer Datenbank.

Ein Servlet würde das ganze in etwa wie folgt an einen Client streamen:

if (myBinaryObject.getContentType()==null ||
     myBinaryObject.getContentType().trim().length()<=0){
  response.setContentType("application/octet-stream");
}
else{
  response.setContentType(myBinaryObject.getContentType());
}
if (myBinaryObject.getName()==null ||
    myBinaryObject.getName().trim().length()<=0){
  response.setHeader("Content-Disposition",
    "filename=unknown");
}
else{
  response.setHeader("Content-Disposition",
    "filename="+myBinaryObject.getName());
}
OutputStream sout = response.getOutputStream();
byte [] data = myBinaryObject.getContent();
sout.write(data, 0, data.length);
sout.flush();

Man beachte, wie der Header des Responseobjektes mit „Content-Disposition“ einen Dateinamen erhält.

In einer JSP sieht der Code fast genauso aus. Auf etwas ist jedoch zu achten.
Bei JSP’s werden üblicherweise alle Zeichen ausserhalb der Java-Blöcke als Text an den Client gestreamt. Dies kann dazu führen, dass Zeichen, wie Leerzeichen, Linefeeds etc. vor oder nach dem Binary Content an den Client gestreamt werden und damit Probleme bereiten.
Auch werden Default-Contenttypes und Headerfelder durch die JSP API gesetzt, welche dann zu Fehlern führen.
Um das alles zu vermeiden, muss lediglich die Methode reset() des ServletResponse-Objektes vor dem Streamen aufgerufen werden, welcher alle bis dahin vorgenommenen Einstellungen und Buffer zurücksetzt. Zusätzlich sollte man nach dem Streamen die JSP-Methode sofort mit return verlassen, damit sich auch am Ende keine Zeichen einschleichen.

response.reset();
// [... das streamen]
return;

Ansonsten sind beide Varianten äquivalent. Die Servlet-Version ist sicherlich schlanker, dafür ist die JSP-Version einfacher zu warten und auszutauschen.

Tags:, , ,

7 Responses to “Download JSPs” »»

  1. Comment by andrej | 15:02 05.10.06|X

    Die Servlet-Version ist sicherlich schlanker, dafür ist die JSP-Version einfacher zu warten und auszutauschen.

    Warum ist die JSP-Version einfacher zu pflegen? Warum ist die JSP-Version einfacher auszutauschen?

  2. Comment by Toni | 17:59 05.10.06|X

    Hm das bringt mich auf eine völlig neue Idee für mein notification Framework. Hatte mich gefragt wie ich intern mit verschiedenartigen Datentypen umgehen soll…du hast es gerade für mich beantwortet…wie logisch eigentlich. Aber du kennst das ja schon…Handauflegen reicht – selbst aus der Ferne! Danke!! 😉

  3. Comment by Secco | 18:07 05.10.06|X

    Warum ist die JSP-Version einfacher zu pflegen? Warum ist die JSP-Version einfacher auszutauschen?

    Nun, die JSP Version ist einfacher auszutauschen und zu warten, da man lediglich die JSP-Datei ändern / austauschen muss und es läuft. Bei Servlets muss man erst Kompilieren, dann die Klasse austauschen und die Webanwendung in Tomcat neustarten. Bei JSP geht das einfacher und schneller…

    verschiedenartigen Datentypen umgehen soll

    Du meinst sicherlich, dass du dir zu jedem Content auch den Contentype merken solltest?

  4. Comment by andrej | 2:18 08.10.06|X

    Nun, die JSP Version ist einfacher auszutauschen und zu warten, da man lediglich die JSP-Datei ändern / austauschen muss und es läuft. Bei Servlets muss man erst Kompilieren, dann die Klasse austauschen und die Webanwendung in Tomcat neustarten. Bei JSP geht das einfacher und schnellerâ¦

    Also das Kompilieren entfällt in gewissen Entwicklungsumgebungen als aktiver Prozess weg. (Beispielsweise Eclipse) Hast du am Tomcat nichts eingestellt, macht er hotdeployment/redeployment. Damit musst du nur die CLASS-Datei in den Ordner Classes kopieren. Oder du richtest dein Projekt so ein, dass es ein Webcontext im Tomcat ist und nichts kopiert werden muss. Tomcat erkennt selbst, wann redeployt werden muss. Andererseits wird die JSP-Datei ja ebenfalls kompiliert, nur eben auf der Seite der Servlet-Engine. D.h. die Zeit fuer das Kompilieren ist immer noch da.

    Dazu kommt auch noch die Tatsache hinzu, dass JSP von den IDEs etwas schlechter unterstuetzt wird als Java. Das erschwert für mich eher die Pflege einer JSP als die Pflege einer Java-Datei. Aber ist ja nur eine Frage der Gewohnheit. Ansonsten ein guter Beitrag. Weiter so!

  5. Comment by Secco | 14:50 08.10.06|X

    Ich gebe dir recht, dass Eclipse die Entwicklung von Klassen und das Deployment in Tomcat perfekt unterstützt, inklusive Hotdeployment, und bei JSPs mit dem Syntaxchecking sehr lagt. Aber für das Depoyment auf einen „produktiv“-Tomcat sind Klassen, vor allem in Jar-Dateien im Verzeichnis lib, nicht so gut geeignet, da in diesem Fall das Hotdeployment von Tomcat nicht so einfach greift. Vielleicht gibt es ja da eine Möglichkeit, die ich nicht kenne.

  6. Comment by Ralf | 19:30 13.10.06|X

    Vielleicht gibt es ja da eine Möglichkeit, die ich nicht kenne.

    Die Möglichkeit gibt es tatsächlich 😉

    Einfach die Anwendung in ein war-Archiv verpacken und unter webapps ablegen, Tomcat kümmerst sich dann von selbst darum, den alten Context herunterzufahren und den neuen zu starten.

  7. Comment by Secco | 10:54 20.10.06|X

    Ich muss leider häufiger einen „Hot-Deploy“ machen, also nur 1-2 Libraries austauschen. Jedesmal das WAR deployen wäre da für mich zu aufwändig…

Leave a Reply »»

Note: All comments are manually approved to avoid spam. So if your comment doesn't appear immediately, that's ok. Have patience, it can take some days until I have the time to approve my comments.