JSP: Datei-Upload vom Client zum Server

+ andere TechDocs
+ HTML
+ JSP
+


Kopieren einer Datei (z.B. einer Bilddatei) vom Client-Rechner per
Web-Browser zum Web Application Server mit JSP (JavaServer Pages).



Inhalt

  1. Einführende Erklärungen
    1. HTML-Formular
    2. JSP-Multipart-Parser
    3. Bilddatei-Eigenschaften
    4. Datei speichern
  2. Konkretes Implementierungsbeispiel
    1. Download der Java-Hilfsklassen
    2. Anpassung der Java-Hilfsklassen
    3. JSP-Programmierbeispiel
    4. Installation auf lokalem Tomcat-Server
    5. Installation auf MyJavaServer.com
    6. Installation auf anderen JSP-Servern
  3. Speichern in und Laden aus SQL-Datenbank


Einführende Erklärungen


HTML-Formular

Grundsätzliche Informationen zu HTML-Formularen finden Sie in html.htm.

Ein übliches HTML-Formular könnte folgendermaßen kodiert werden:


<html>
<body>
<form action="index.jsp" enctype="application/x-www-form-urlencoded" method="POST">
<input type="text" name="myText">
<input type="submit" value="OK">
</form>
</body>
</html>

Um eine Datei vom Client zum Server zu laden, muss das HTML-Formular etwas anders formuliert werden:


<html>
<body>
<form action="index.jsp" enctype="multipart/form-data" method="POST">
<input type="file" name="myFile">
<input type="submit" value="Upload">
</form>
</body>
</html>

Für Datei-Upload muss im HTML-Formular also folgendes gesetzt sein:

Wie das Beispiel zeigt, plaziert der Web-Browser automatisch einen 'Durchsuchen...'-Button neben das 'input-file'-Eingabefeld. Über diese Schaltfläche können Sie in Ihrem lokalen Dateisystem eine Datei auswählen. Übrigens werden dabei die Informationen über Ihre lokalen Dateien zwar im Web-Browser-Dialog angezeigt, aber nicht zum Web-Server weitergegeben. Erst nach Betätigung des 'submit'/'Upload'-Buttons gelangt der Dateiname und Dateiinhalt der ausgewählten Datei zum Server.


JSP-Multipart-Parser

Grundsätzliche Informationen zu JSP finden Sie unter index.htm#JSP.

Während per enctype="application/x-www-form-urlencoded" übertragende Formulareinträge auf der Server-Seite in einer JSP-Datei einfach per

String meinParameter = request.getParameter( "meinParameter" );

gelesen werden können, ist das bei enctype="multipart/form-data" leider nicht möglich. Der JSP-Parameter-Parser muss durch einen anderen Multipart-tauglichen Parser ersetzt werden.

Im Internet finden Sie viele Implementationen von Multipart-Parsern, z.B.

Eine ausführliche Beschreibung, wie ein Multipart-Parser intern funktioniert, finden Sie bei:


Bilddatei-Eigenschaften

Da es sich beim Datei-Upload häufig um Bilddateien handelt, soll noch ein Modul vorgestellt werden, das Informationen aus Bilddateien extrahieren kann:

Es bietet u.a. folgende Funktionen:

Weitergehende Informationen zu Grafikausgabe und Bildverarbeitung in Java finden Sie in java-img.htm.


Datei speichern

Grundsätzliche Informationen zu Dateioperationen in Java finden Sie in java-io.htm.

Beim Umgang mit der Upload-Datei muss auf der Server-Seite zwischen zwei Pfaden unterschieden werden:

Ersterer wird zum Beispiel benötigt, wenn das Ergebnis als Bilddatei in eine HTML-Seite eingebettet werden soll.
Zweiterer wird benötigt, um die Datei auf der Server-Seite zu speichern.
Die Umwandlung von Ersterem in den Zweiten erfolgt mit getServletContext().getRealPath(). Unter Windows werden dabei auch die Schrägstriche '/' durch Backslashes '\' ersetzt.

Die Speicherung erfolgt bei Binärdaten als FileOutputStream(), wie der folgende Code-Ausschnitt zeigt:


// Different file pathes for HTML and for storing:
String sFilePathAndNameHtml = sUploadDir + sFileName;
String sFilePathAndNameStore
  = getServletContext().getRealPath( sFilePathAndNameHtml );
// Store file:
BufferedInputStream  is = null;
BufferedOutputStream os = null;
try {
  is = new BufferedInputStream( inputStreamFromParser );
  os = new BufferedOutputStream(
       new FileOutputStream( sFilePathAndNameStore ) );
  byte[] buff = new byte[8192];
  int len;
  while( 0 < (len = is.read( buff )) )
    os.write( buff, 0, len );
} finally {
  if( is != null )
    is.close();
  if( os != null ) {
    os.flush();
    os.close();
  }
}


Konkretes Implementierungsbeispiel


Download der Java-Hilfsklassen

Downloaden Sie folgende Dateien:

Entpacken Sie beide ZIP-Dateien. Sie benötigen nur die folgenden drei Dateien:

Wohin diese drei Dateien kopiert werden müssen, hängt vom JSP-Server ab und wird weiter unten beschrieben. Vorläufig reicht irgendein temporäres Verzeichnis.


Anpassung der Java-Hilfsklassen

In dieser Beschreibung wird von bestimmten Verzeichnisstrukturen und Pfadnamen ausgegangen (.../torstenhorn/upload). Bitte ersetzen Sie die angegebenen Strukturen und Pfadnamen durch die von Ihnen benutzten. Falls Sie planen, Ihre Anwendung auf einen JSP-Server ähnlich zu 'MyJavaServer.com' einzusetzen, beachten Sie bitte, dass Sie statt 'torstenhorn' Ihren Login-Namen einsetzen müssen.


Fügen Sie in alle drei Dateien als erste Zeile ein:

package torstenhorn.upload;

Entfernen Sie anderslautende 'package'-Zeilen, also in den beiden Dateien MultipartRequest.java und ServletMultipartRequest.java jeweils die Zeile:

package http.utils.multipartrequest;

Um bei einigen Compilern Fehlermeldungen zu vermeiden, ändern Sie in der Datei MultipartRequest.java die Zeile 163 von

new String(new byte[]{'\n'}, enc);

nach

new String(new byte[]{(byte)'\n'}, enc);

JSP-Programmierbeispiel

Markieren Sie im Web-Browser den folgenden grau hinterlegten Quelltext und speichern Sie ihn in der neu anzulegenden Datei:

Falls Sie einen anderen Dateinamen wählen, passen Sie bitte die Zeile '<form action="index.jsp" ...>' an.

Tragen Sie bei 'String sUploadDir = "/upload/"' den von Ihnen gewünschten Verzeichnisnamen für die Upload-Dateien ein. Dieser Eintrag muss mit einem Schrägstrich '/' beginnen und enden und das entsprechende Verzeichnis muss im JSP-Web-Server vorher angelegt werden.

In diesem Beispiel wird davon ausgegangen, dass nur Bilddateien zum Upload erlaubt sein sollen. Nach dem Upload werden sie in die Webseite eingebettet und sofort angezeigt. Falls Sie andere Dateien uploaden wollen, müssen die entsprechenden einschränkenden Zeilen entfernt werden, z.B.:
'if(!ii.check())', 'if(!sImgFormat.equals("..."))' und '<img src="...">'.


<%--
  Comment to this file see:
  http://www.Torsten-Horn.de/techdocs/jsp-upload.htm

  Uses Jason Pell's MultipartRequest to upload a file:
  http://www.geocities.com/jasonpell/programs.html

  Uses Marco Schmidt's ImageInfo to get image file information:
  http://schmidt.devlib.org/image-info
--%>

<%@ page import = "java.io.*, torstenhorn.upload.*" %>

<%!
  // Adapt the following string for your upload directory.
  //   Tomcat local     :  sUploadDir = "/upload/";
  //   MyJavaServer.com :  sUploadDir = "/~torstenhorn/upload/";
  final String sUploadDir = "/upload/";
  final String sErrMsg
    = "<h2>Fehler: Keine gültige Bilddatei (JPG, PNG, GIF)!</h2>";

  String readAndShowImage( HttpServletRequest request )
  throws FileNotFoundException, IOException
  {
    String sRet = "";
    // Check for valid parameter data:
    if( !request.getMethod().equals( "POST" ) )
      return "";
    MultipartRequest parser
      = new ServletMultipartRequest( request, 1*1024*1024 );  // < 1 MB
    if( null == parser ||
        null == parser.getFileContents( "myFile" ) )
      return "";
    // Check for valid image file:
    ImageInfo ii = new ImageInfo();
    if( null == ii )
      return "";
    ii.setInput( parser.getFileContents( "myFile" ) );
    if( !ii.check() )
      return sErrMsg;
    // Note: Parameters are in the parser and not in request:
    String myComment  = parser.getURLParameter( "myComment" );
    String sFileName  = parser.getFileSystemName( "myFile" );
    String sImgFormat = ii.getFormatName().toLowerCase();
    // Show image data:
    if( null == sImgFormat )
      sImgFormat = "Unbekanntes Format";
    if( sImgFormat.equals( "jpeg" ) )
      sImgFormat = "jpg";
    sRet = "<h2>" + sFileName + ":</h2>"
           + sImgFormat.toUpperCase() + ", "
           + ii.getWidth() + " x " + ii.getHeight() + " pixels, "
           + ii.getBitsPerPixel() + " bpp, "
           + parser.getFileSize( "myFile" ) + " Bytes<br>\n";
    // Check if image format is suitable for inserting into HTML page:
    if( !sImgFormat.equals( "jpg" ) &&
        !sImgFormat.equals( "png" ) &&
        !sImgFormat.equals( "gif" ) )
      return sRet + sErrMsg;
    // Generate valid file name. Different operating systems or 
    // browsers may return the file name with or without path 
    // and the path may contain '/' (Unix) or '\' (Windows):
    if( null == sFileName || 0 >= sFileName.length() )
      sFileName = "MyFile";
    char c = sFileName.charAt( sFileName.length() - 1 );
    if( '/' == c || '\\' == c )
      sFileName = sFileName.substring( 0, sFileName.length() - 1 );
    int i;
    if( 0 <= (i = sFileName.lastIndexOf( '/' )) )
      sFileName = sFileName.substring( i + 1 );
    if( 0 <= (i = sFileName.lastIndexOf( '\\' )) )
      sFileName = sFileName.substring( i + 1 );
    if( !sFileName.toLowerCase().endsWith( "." + sImgFormat ) )
      sFileName += "." + sImgFormat;
    // Different file pathes for HTML page and for storing:
    String sFilePathAndNameHtml = sUploadDir + sFileName;
    String sFilePathAndNameStore
      = getServletContext().getRealPath( sFilePathAndNameHtml );
    // Store file:
    BufferedInputStream  is = null;
    BufferedOutputStream os = null;
    long sum=0;
    try {
      is = new BufferedInputStream( parser.getFileContents( "myFile" ) );
      os = new BufferedOutputStream(
           new FileOutputStream( sFilePathAndNameStore ) );
      byte[] buff = new byte[8192];
      int len;
      while( 0 < (len = is.read( buff )) ) {
        os.write( buff, 0, len );
        sum += len;
      }
    } finally {
      if( is != null )
        is.close();
      if( os != null ) {
        os.flush();
        os.close();
      }
    }
    sRet += "Gespeichert: " + sum + " Bytes<br>\n";
    if( null != myComment && 0 < myComment.length() )
      sRet += "Kommentar: " + myComment + "<br>\n";
    sRet += "<br><img src='" + sFilePathAndNameHtml + "'"
          +         " alt='" + sFileName + "'"
          +         " height=" + ii.getHeight()
          +         " width=" + ii.getWidth() + "><br>\n"
          + "<br>\n sFilePathAndNameHtml  = " + sFilePathAndNameHtml
          + "<br>\n sFilePathAndNameStore = " + sFilePathAndNameStore
          + "<br>\n getRealPath(request.getRequestURI()) = "
          +  getServletConfig().getServletContext().
                 getRealPath(request.getRequestURI());
    return sRet;
  }
%>

<html>
<head>
  <title>Bilddatei-Upload</title>
</head>
<body>

<h2>Upload einer Bilddatei vom Client zum Server</h2>

<form action="index.jsp" enctype="multipart/form-data" method="POST">

<table>
  <tr>
    <td>Kommentar (optional):</td>
    <td><input type="text" name="myComment" size=40 maxlength=255></td>
  </tr>
  <tr>
    <td>Bilddatei (JPG, PNG, GIF):</td>
    <td><input type="file" name="myFile"    size=40 maxlength=255>
        <input type="submit" value="Upload"></td>
  </tr>
</table>

</form>

<br>
<%= readAndShowImage( request ) %>

</body>
</html>

Installation auf lokalem Tomcat-Server

Im folgenden wird davon ausgegangen, dass Sie Java und Tomcat unter Windows installiert haben, wie unter jsp-install.htm beschrieben ist. Andernfalls müssen Sie die Pfadangaben entsprechend anpassen.

Kopieren Sie die vier Dateien

in das neu anzulegende Verzeichnis 'D:\Tools\Tomcat\webapps\ROOT\upload'.

Erzeugen Sie in diesem Verzeichnis eine Batch-Datei mit folgendem Inhalt:


cls
set JAVA_HOME=C:\Program Files\Java\jdk1.6
set CATALINA_HOME=D:\Tools\Tomcat
set CLASSPATH=.;%CATALINA_HOME%\lib\servlet.jar
@set pathold=%path%
@set path=%JAVA_HOME%\bin;%path%
javac -d ..\WEB-INF\classes *.java
@set path=%pathold%
@set pathold=

Passen Sie die Einträge 'set JAVA_HOME=C:\Program Files\Java\jdk1.6' und 'set CATALINA_HOME=D:\Tools\Tomcat' an Ihre Pfade an und führen Sie die Batch-Datei aus. Als Ergebnis erhalten Sie drei '*.class'-Dateien im Verzeichnis:
'D:\Tools\Tomcat\webapps\ROOT\WEB-INF\classes\torstenhorn\upload'.

Starten Sie den Tomcat-JSP-Server neu und rufen Sie im Web-Browser auf:


Installation auf MyJavaServer.com

Ersetzen Sie in den vier Dateien

überall 'torstenhorn' durch Ihren Login-Namen, also zum Beispiel in den Zeilen:

und kopieren Sie die vier Dateien (per FTP) in das neu anzulegende Unterverzeichnis 'upload' unter Ihrem MyJavaServer.com-Account. Die Dateien brauchen nicht manuell kompiliert zu werden.

Prüfen Sie, dass 'sUploadDir' korrekt gesetzt ist und dass das entsprechende Verzeichnis angelegt ist (falls Sie ein anderes gewählt haben).

Ersetzen Sie auch in folgendem Link 'torstenhorn' durch Ihren Login-Namen und geben Sie die Adresse im Web-Browser ein:


Installation auf anderen JSP-Servern

Die Installation unter anderen JSP-Servern verläuft ähnlich wie oben für Tomcat und MyJavaServer.com beschrieben.

Manchmal kann es etwas schwierig sein, die notwendigen Pfadangaben zu ermitteln. Dann sollten Sie mit folgender JSP-Datei die absoluten Pfade im Dateisystem des JSP-Servers ermitteln:


<html>
<body>
Absolute Pfade im Dateisystem des JSP-Servers:<br>
<pre>
<%= getServletConfig().getServletContext().getRealPath( "/" ) %><br>
<%= getServletConfig().getServletContext().getRealPath( request.getRequestURI() ) %><br>
</pre>
</body>
</html>


Speichern in und Laden aus SQL-Datenbank

... ist beschrieben in java-sql.htm#BLOB.





Weitere Themen: andere TechDocs | HTML | JavaScript | JSP | SQL | Webanwendungen
© 1998-2007 Torsten Horn, Aachen