# FileUpload ohne Servlets



## ASD20054 (17. März 2006)

hi,

hat jemand einen Codeschnipsel da wie ich ein Bild mittels multipart/form-data und Get hochladen kann? Das heißt ich habe ein Formular Upload.html was mittels eines Java Server betrieben wird. Nur muss ich halt den Upload Code in die *.java datei schreiben damit er das Bild hochlädt. Kann mir wer weiterhelfen?


```
private void upload() 
	{
                //hier müsste dann der Code stehen.
	}
```

Bitte keine Servlet Beispiele!


----------



## xardias (20. März 2006)

Du kannst nicht einfach eine Java Klasse ohne Servlet oder sonstwas aufrufen.
Warum willst du kein Servlet benutzen? Da heißt die methode dann nicht upload sondern einfach doPost. Du musst entweder ein JSP oder ein Servlet benutzen.
Und in beiden fällen sollte dir Commons FileUpload hilfreich sein:
http://jakarta.apache.org/commons/fileupload/


----------



## takidoso (20. März 2006)

Hallole
Ich glaube damit jemand Dir eine gute Antwort geben kann, solltest Du vielleicht noch etwas mehr spezifizieren.
Wenn ich mal so mutmaße möchtest Du einem schon existierenden Server etwas hochladen, richtig? Wie sieht es mit dem Protokoll aus, ist es HTTP oder ist es FTP ?
Wenn es HTTP ist nehme ich an, dass Du mit dem Schlagwort HTTP-Client weiter kommen könntest. und falls es FTP sein sollte vielleicht mit dem Schlagwort FTP-Client.

Ist aber nur eine Annahme.

Takidoso


----------



## takidoso (20. März 2006)

xardias hat gesagt.:
			
		

> Du kannst nicht einfach eine Java Klasse ohne Servlet oder sonstwas aufrufen.



Also alles was eine Java-Klasse benötigt um aufgerufen zu werden ist eine main-routine und dann natrülich etwas was die JVM startet und die besagte Klasse 'übergibt' zum Beispiel eine Batch-Datei. Oder bezieht Deine "sonstwas" sich auf diese Möglichkeit?


----------



## xardias (20. März 2006)

Sorry, ich Depp habe die Frage etwas falsch verstanden. Ich dachte er wolle den serverseitigen Part des uploads ohne Servlets realisieren.
Entschuldigt bitte 

Aber um Thema: Ich denke dir sollte Commons HttpClient weiterhelfen: http://jakarta.apache.org/commons/httpclient/
Damit kannst du jeder beliebigen Java Anwendung mit Zugang zum Internet HTTP anfragen senden und antworten empfangen.
Speziell diese Beispielanwendung könnte dich Interessieren:


----------



## Billie (20. März 2006)

Hellas!

Also ich bin so ungeniert und schreib mein Problem jetzt hier an diesem Thread dazu. Ich will nämlich ungefähr das Selbe lösen, also ein Programm/Applet welches Datei(en) an den Server schieckt, mittelst Post. Ich bin auch schon sehr weit nur meine POST Daten werden im PHP Skript (phpinfo()) einfach nicht angezeigt. Es folgt die komplette POST-Anfrage wie sie vom ECHO-Server zurückgegeben wird:


```
POST /phpinfo.php HTTP/1.1\r\n
Content-Type: multipart/form-data; boundary=-----------1234\r\n
Cache-Control: no-cache\r\n
Pragma: no-cache\r\n
User-Agent: Java/1.5.0\r\n
Host: localhost:80
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n
Connection: keep-alive\r\n
Content-Length: 92\r\n
\r\n
-----------1234\r\n
Content-Disposition: form-data; name="test1"\r\n
\r\n
Text\r\n
-----------1234--\r\n
\r\n
```


```
String boundary = "-----------1234";

				URL url = new URL("http://localhost:7/phpinfo.php");
				HttpURLConnection conn = (HttpURLConnection)url.openConnection();
				conn.setRequestMethod("POST");
				conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
				conn.setDoOutput(true);
				conn.setUseCaches(false);

				ByteArrayOutputStream byteStream = new ByteArrayOutputStream(512);

				String content = boundary + "\r\n"
								 + "Content-Disposition: form-data; name=\"test1\"\r\n"
								 + "\r\n"
								 + "Test\r\n"
								 + boundary + "--\r\n\r\n";

				byte[] bytes = content.getBytes();

				byteStream.write(bytes, 0, bytes.length);
				byteStream.writeTo(conn.getOutputStream());
```

Ich hoffe ihr könnt mir Anhaltspunkte geben....

lg Billie


----------



## xardias (21. März 2006)

So direkt kann ich dir da gerade leider nicht helfen. aber vielleicht möchtest du ja commons http client verwenden, welches eigentlich relativ leicht zu verwenden ist:
http://jakarta.apache.org/commons/httpclient/methods/multipartpost.html


----------



## Billie (21. März 2006)

Also ich werde mir evtl. mal den Source Code ansehen, aber eigentlich das Problem selbst lösen und wissen, warum das so einfach nicht funktioniert. Einfache POST-Anfragen funktionieren, aber was er mir an den Multipart POST Anfragen nicht mag?!


----------



## Billie (21. März 2006)

Hab den "Fehler" gefunden. Ich bin auf ungereimtheiten zwischen der Content-Length Angabe von meinem Java Programm und der Angabe von IE gestoßen. Der IE hatte immer um einige Zeichen mehr und die fehlenden Zeichen hab ich gefunden...

Ich habe ein Boundary definiert "--1234", im der Content-Type Angabe passt dieses Boundary so. Im Content-Teil muss das Boundary nochmal um zwei "--" erweitert werden, also "----1234".

lg Billie


----------



## ASD20054 (22. März 2006)

Hallo,
Sorry für meine wenigen Angaben. Ich kann auf dem Server was ich benutz leider keine Servlets verwenden. Da es ein HTTP Stream Chat Server ist (frettjc) und der keine Servlets unterstützt. Ich habe schon versucht das mit den jakarta commons zu machen doch leider weiss ich nicht wie ich das anstellen soll. Ich möchte das die User ein Bild Uploaden können. Wer sich gern mal den Source Code anschauen möchte , denn kann ich gerne den Chat schicken. Versuch das schon seit einem halben Jahr hinzubekommen doch es wird nichts da mir keiner in den Foren Helfen möchte


----------



## Billie (23. März 2006)

Ich hab ein Programm geschrieben, was eigentlich genau das erledigt... du brauchst nur ein PHP Skript, welches dir die Datei am Server entgegen nimmt.


```
URL url = new URL("http://localhost:80/upload.php");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
String boundary = "---------------------------" + createBoundary(srcFile.toString());
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
conn.setDoOutput(true);
conn.setUseCaches(false);

Image img = new ImageIcon(ImageIO.read(srcFile)).getImage();
BufferedImage outImg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);

Graphics g = outImg.getGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();

ByteArrayOutputStream byteStream = new ByteArrayOutputStream(512);

String content = "--" + boundary + "\r\n"
				 + "Content-Disposition: form-data; name=\"upload_file\"; filename=\"" + srcFile.toString() + "\"\r\n"
				 + "Content-Type: image/pjpeg\r\n"
				 + "\r\n";

byte[] bytes = content.getBytes();

byteStream.write(bytes, 0, bytes.length);
ImageIO.write(outImg, "jpg", byteStream);

content = "\r\n--" + boundary + "\r\n"
		+ "Content-Disposition: form-data; name=\"feld\"\r\n"
		+ "\r\n"
		+ "Inhalt\r\n"
		+ "--" + boundary + "--\r\n";

bytes = content.getBytes();
byteStream.write(bytes, 0, bytes.length);

byteStream.writeTo(conn.getOutputStream());

if(conn.getResponseCode() != HttpURLConnection.HTTP_OK) {

	// HTTP Anfrage erforlgreich abgesetzt
}
```

In PHP würdest du bei phpinfo() die Variablen $_FILES["upload_file"] und $_POST["feld"] sehen. Hier noch die Methode, mit welcher ich mein boundary generiere:


```
// benötigt java.security.*; Package

	public String createBoundary(String s)
		throws NoSuchAlgorithmException {

		MessageDigest md = MessageDigest.getInstance("MD5");
		md.update(s.getBytes());
		byte[] digest = md.digest();
		String boundary = "";

		for(int i = 0; i < digest.length; i++) {

			boundary += Integer.toHexString(digest[i] & 0xFF);
		}

		return boundary;
	}
```

lg Billie

[edit]Hab den Code für das Vekleinern des Bildes entfernt, bei mir war die Vorgabe Bild hat eine max. Höhe/Breite von 400px und wird automatisch verkleinert und dann erst zum Server geschieckt. Wenn du das Ganze als Applet realisierst, gibt es theoretisch keine Probleme wegen der Verbindung (ein Applet darf sich zum Server, von welchem es angefordert wurde, verbinden) aber was ich mich selbst gefragt habe, ist das Zugreifen auf die Bilddateien ... also der Benutzer wählt eine Datei aus, welche von seinem Rechner stammt und diese würd übertragen. Ich glaube, da geht es ohne Signierung des Applets nicht.[/edit]


----------



## Nekoko-chan (13. Mai 2006)

Hallo

da ich zur Zeit auch mit dem Upload von Bildern zu kämpfen habe, bin ich auf dieses Board gestoßen... Ich hab deinen Code gleich ausprobieren wollen, das Problem ist nur, dass die Variablen $_FILES["upload_file"] und $_POST["feld"] dort irgendwie nicht auftauchen. Und die Datei wird folglich auch nicht erstellt....


Woran kann das eigentlich liegen? Bei anderen Beispielen, die ich getestet habe, ist es leider genauso.
Langsam bin ich nämlich richtig frustriert, dass die Lösung anscheinend so nah ist, und ich sie trotzdem nicht finden kann


----------



## Billie (15. Mai 2006)

Also wenn du in phpinfo() keine $_POST Variablen angezeigt bekommst und du auch keinen Fehler vom Server bekommst (einen anderen Error Code als HTTP_OK bzw. 200) solltest du deine Anfrage lokal testen.

Ich habe hierzu den Echo Server von http://www.javabuch.de/ verwendet. Hierzu kompilierst und startest du einfach folgende Java-Anwendung:


```
/* EchoServer.java */

import java.net.*;
import java.io.*;

public class EchoServer
{
  public static void main(String[] args)
  {
    int cnt = 0;
    try {
      System.out.println("Warte auf Verbindungen auf Port 7...");
      ServerSocket echod = new ServerSocket(7);
      while (true) {
        Socket socket = echod.accept();
        (new EchoClientThread(++cnt, socket)).start();
      }
    } catch (IOException e) {
      System.err.println(e.toString());
      System.exit(1);
    }
  }
}

class EchoClientThread
extends Thread
{
  private int    name;
  private Socket socket;

  public EchoClientThread(int name, Socket socket)
  {
    this.name   = name;
    this.socket = socket;
  }

  public void run()
  {
    String msg = "EchoServer: Verbindung " + name;
    System.out.println(msg + " hergestellt");
    try {
      InputStream in = socket.getInputStream();
      OutputStream out = socket.getOutputStream();
      out.write((msg + "\r\n").getBytes());
      int c;
      while ((c = in.read()) != -1) {
        out.write((char)c);
        if((char) c == '\n') System.out.print("\\n\r\n");
        else if((char) c == '\r') System.out.print("\\r");
        else System.out.print((char)c);
      }
      System.out.println("Verbindung " + name + " wird beendet");
      socket.close();
    } catch (IOException e) {
      System.err.println(e.toString());
    }
  }
}
```

Dann änderst du noch deine URL-Adresse zu der die Verbindung herstellst auf deinen lokalen Host und dem Port 7, also

http://localhost:7/upload.php

... die PHP-Datei ist eigentlich irrelevant, da du von diesem Server keine Antwort bekommen wirst du siehst nur die Anfrage und kannst diese dann auf Korrektheit überprüfen.

Wie gesagt, so habe ich mein Problem entdeckt.

mfg Billie


----------



## kirie (18. Juni 2006)

Hallo Billie,

ich habe Deinen Code ausprobiert um eine Datei auf einen Server zu laden.
Auf jeden Fall vielen Dank, dass Du Deine Idee zur Verfügung stellst.

In der Zeile 37: byteStream.writeTo(conn.getOutputStream());
Tritt bei mir jedoch eine Exception auf:
java.net.ProtocolException: Already connected!

Hattest Du das Problem auch?

Gruß
kirie


----------



## Billie (19. Juni 2006)

Hellas,

Nein hatte leider nie diesen Fehler. Ich verstehe sie eigentlich auch nicht ganz, da es ja nur recht ist, dass eine Verbindung besteht. Aber evtl. probiert er sich erneut zu verbinden.

Ich werde es mir am Nachmittag nochmal ansehen. Trotzdem könntest du evtl. deinen gesamten Code posten.


----------



## Thomas Darimont (19. Juni 2006)

Hallo!

Ich denke die einfachste Loesung einen einfachen Datei-Upload zu bauen ist der eine fertige Upload Komponente zu verwenden.

Ich benutze beispielsweise diese hier:
http://forum.java.sun.com/thread.jspa?forumID=256&threadID=451245

Gruss Tom


----------



## Crach (26. April 2007)

Hey,

Werd mal dieses "alte" thema mit einer neuen frage entstauben^^..

Folgendes Problem: Ich will einen String von Java aus mittels CGI-Script auf einem server speichern lassen - als textdatei.


```
URL bildcgiURL=null;   

bildcgiURL = new URL("http",getCodeBase().getHost(),"/cgi-bin/bildupload.cgi");

HttpURLConnection conn = (HttpURLConnection)bildcgiURL.openConnection();

conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setDoInput(true);

String bildcgi="";

BufferedReader bildbr=null;
DataOutputStream bilddos=null;    
            

System.out.println(bildcgiURL);
try 
{
	bilddos = new DataOutputStream(conn.getOutputStream());
	bilddos.writeBytes(data);
	System.out.println("Login geht");
	
	bildbr = new BufferedReader(new InputStreamReader(conn.getInputStream()));
	bildcgi = bildbr.readLine();

	bilddos.close(); 
	bildbr.close();
}
catch(MalformedURLException e) 
{
	e.printStackTrace();
}
catch(IOException ex) 
{ 
	ex.printStackTrace();
}
```

Mit dem Code hab ich s versucht, nur die datei bleibt leer -> Ich vermute, er übergibt die Daten nicht richtig. 
Das CGI-Script funktioniert sonst wunderbar, also mittels..


```
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Unbenanntes Dokument</title>
</head>

<body>
<form action="/cgi-bin/bildupload.cgi" method="post" name="data">
Eingabe: <input type="text" name="data"> <input type=submit>
</form>
</body>
</html>
```

kann ich die datei+inhalt erstellen(zum testen des cgi-Scriptes). Was müsst man an dem Java-quelltext ändern, damit er die daten korrekt übergibt?

thx


----------

