# Formular



## bronks (4. Aug 2005)

Hi!

Folgender JSP-Code der Datei "zTest.jsp":


```
<% out.println(request.getParameter("textfeld"));
out.println("
");
%> 

<form method="post" action="zTest.jsp" enctype="multipart/form-data">
    Dateiname:<input type="file" size="30" name="filename" value="null">
    <input type="text" name="textfeld" value="Irgendetwas">
    <input type="submit" value="Drück mich">
</form>
```

Wenn ich auf den Submitbutton drücke, dann sollte auf dem Bildschirm die gleiche Seite erscheinen, nur daß oben "Irgendetwas" steht. Das funktioniert leider nicht. 

Wenn ich das gleiche mit PHP mache und statt dem Javatext ein einfaches "echo $textfeld" schreibe, dann wird mit "Irgendetwas" angezeigt.

Was mache ich verkehrt? Bitte Hilfe!

Danke!

Bronks


----------



## Bleiglanz (4. Aug 2005)

lass den enctype weg


----------



## bronks (4. Aug 2005)

Bleiglanz hat gesagt.:
			
		

> lass den enctype weg


Dann habe ich aber ein neues Problem: Das Formular schickt mir die Datei nicht weg!

Ich plante das ganze so: Der Dateiname wird mit einer zusätzlichen Info in der DB gespeichert. Danach wird die Datei geladen und in eine DB geschrieben.


----------



## Bleiglanz (4. Aug 2005)

unter jsp musst den fileupload mit einer eigenen bibliothek machen, da ist das leider nicht so einfach wie unter php

(fileupload ist nicht in der Spec! echter Schwachpunkt bei J2EE)


=> jakarta.commons.FileUpload besorgen und die normalen Textfelder damit auslesen...


----------



## bronks (4. Aug 2005)

Bleiglanz hat gesagt.:
			
		

> => jakarta.commons.FileUpload besorgen und die normalen Textfelder damit auslesen...


Für den Upload verwende ich die von Dir genannte Lib. Es funktioniert einwandfrei. Für das Senden der Daten ist doch der Browser zuständig? Die Lib nimmt die empfangenen Daten nur entgegen!?!

Das Problem liegt darin, daß wenn der Enctype auf "multipart/form-data" gesetzt ist, von dem empfangenden Servlet nur die Dateien erkannt werden und sonst nichts. Wenn dagegen der Enctype nicht angegeben wird, dann habe komme ich an die Daten des Textfeldes ran, aber die Datei wird nicht gesendet.

Ich hab den Verdacht, daß Java nicht in der Lage ist, zu erkennen was in dem Request alles drinsteckt. Entweder werden die Dateien gesendet oder die Texte ... oder es wir nicht richtig er kannt?


----------



## bronks (4. Aug 2005)

Hab die Sache jetzt mal auf einem anderen Server getestet. Das gleiche Ergebnis. 

Ich habe das ganze jetzt mal gedebugt und man wird es nicht glauben: Das Textfeld wird als Datei erkannt. Genau deshalb läuft mit getParameter()  da rein garnix. Wenn man jetzt verlangt, daß die Datei irgendwo hingeschrieben wird, dann bricht plötzlich Ahnungslosigkeit und Panic in der JVM aus. Damit das ganze nicht ganz so dumm aussieht erhält man diese Exception: "Software caused connection abort: recv failed"


----------



## Bleiglanz (4. Aug 2005)

jajaja

beim dateiupload funzt getParameter nicht

=> die lib bietet dir die möglichkeit, diese felder auszulesen schau ahlt in die API doc


> => jakarta.commons.FileUpload besorgen und die normalen Textfelder damit auslesen...


meinte


> => jakarta.commons.FileUpload besorgen und *auch*die normalen Textfelder damit auslesen...


----------



## KSG9|sebastian (5. Aug 2005)

Ich hab ein FileUpload-Portlet geschrieben (Testweise..) in dem funktioniert es, dass ich die Werte von Textfeldern auslese UND die Datei hochlade, und zwar so wie Bleiglanz es sagt, über die jakarta.commons.FileUpload-Klasse...


----------



## bronks (5. Aug 2005)

@Bleiglanz: Vielen Dank! Das mit dem macht mir manchmal noch probleme 

@KSG9|plak:
Danke!

@all:
Da wäre ich im Traum nicht draufgekommen, daß man die Sache so angehen muß!


----------



## Gumble (25. Aug 2005)

KSG9|plak hat gesagt.:
			
		

> Ich hab ein FileUpload-Portlet geschrieben (Testweise..) in dem funktioniert es, dass ich die Werte von Textfeldern auslese UND die Datei hochlade, und zwar so wie Bleiglanz es sagt, über die jakarta.commons.FileUpload-Klasse...



Bin gerade auch dabei ein kleines Portlet zu schreiben: es soll eine Fileupload-form haben und eine Tabelle, die die (persistenten) Daten anzeigt. Nur hab ich das Problem dass ich in der doView-Methode nicht an die Parameter rankomme. Bzw, die parse-Methode moechte ein HttpRequest - Object haben:

```
List fileItems = fu.parseRequest(req);
```
ich habe leider nur ein _RenderRequest_.
jsp:

```
<form name="frm1" nethod="post" action="">  
	<input name="pdfile" type="file" accept="text/xml">   
   <input type="submit" name="button1" value="Load"> 
</form>
```

Bin leider nicht so ganz fit mit dem Web-krams. 
KSG9|plak: wie hast du das geloest?
Danke schon mal fuer die Hilfe


----------



## Gumble (25. Aug 2005)

ok, das eine Problem hab ich geloest: berichtigt mich bitte wenn was falsch ist!
Parameterzugriff auf das http-POST geht nur in der _ProcessAction_ Methode. Um die zu starten muss das Form eine ensprechende Action ausfuehren.

```
<form Name="frm1" Method="post" Action="<%= request.getAttribute("formActionUrl") %>">  
	<input name="pdfile" type="file" accept="text/xml">&<input type="submit" name="button1" value="Load"> 
</form>
```
Leider konnte ich nicht direkt die ActionUrl im jsp erzeugen so dass ich das Objekt erstmal im Request uebergeben musste:

```
request.setAttribute("formActionUrl", response.createActionURL());
```

1. geht das vielleicht irgendwie schoener?
2. wie kann ich das FileUpload dazu überreden dass es funktionert? in der ProcessAction-Methode hab ich nun ein _ActionRequest_Objekt - will aber gern das HttpServletRequest haben  ???:L


----------



## Gumble (25. Aug 2005)

Dann mach ich mal mit dem Selbstgespraech weiter :roll: 



			
				Gumble hat gesagt.:
			
		

> 1. geht das vielleicht irgendwie schoener?


Mit Taglibs:

```
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<portlet:defineObjects/>
<form action=<portlet:actionURL/> enctype="multipart/form-data" method="post">
```
Anmerkung: enctype="multipart/form-data" muss gesetzt sein!

Dazu ne Frage: die portlet.tld steckt doch sicher auch in irgendeiner 'Basic'-jar? Ich will eigentlich nicht in jedem Portlet das Dingens reinkopieren - vielleicht ändert sie sich ja mal? Wie kann ich auf eine/die Taglib referenzieren?



			
				Gumble hat gesagt.:
			
		

> 2. wie kann ich das FileUpload dazu überreden dass es funktionert? in der ProcessAction-Methode hab ich nun ein _ActionRequest_Objekt - will aber gern das HttpServletRequest haben  ???:L



http://jakarta.apache.org/commons/fileupload/ - Auf der Download-Page ist nichts zu erkennen, die Javadoc verraet aber, dass die an einer Version 1.1 basteln - diese hat ein _PortletFileUpload_-Objekt:

```
PortletFileUpload dfu = new PortletFileUpload();
List fileItems = null;
try {
	fileItems = dfu.parseRequest(request);
	Iterator iter = fileItems.iterator();
[...]
```
Das kann nun die passenden ActionRequest-Objekte verdauen. 
Nur leider gibts immernoch Probleme: (

15:13:10,504 INFO  [STDOUT] java.lang.NullPointerException
15:13:10,504 INFO  [STDOUT]     at org.apache.commons.fileupload.FileUploadBase.createItem(FileUploadBase.java:488)
15:13:10,504 INFO  [STDOUT]     at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:359)
15:13:10,514 INFO  [STDOUT]     at org.apache.commons.fileupload.portlet.PortletFileUpload.parseRequest(PortletFileUpload.java:101)
15:13:10,514 INFO  [STDOUT]     at ***********.DefinitionOverViewPortlet.processAction(DefinitionOverViewPortlet.java:88)
15:13:10,514 INFO  [STDOUT]     at org.jboss.portal.portlet.invocation.DispatcherInterceptor.invokeAction(DispatcherInterceptor.java:110)
Irgendwie scheint das parseRequest aber nicht zu funktionieren.

btw: 
commons-fileupload-20050825.zip (nightly build)
JDK 1.5.0_04
jBoss as 4.0.2
jBoss Portal 2.0


----------



## KSG9|sebastian (25. Aug 2005)

1. guckst du hier:

http://portals.apache.org/pluto/multiproject/pluto-portal/xref/org/apache/commons/fileupload/


2. dein formular muss ein Datei-Auswahl-Feld enthalten UND ein "normales" textfeld, sonst kriegst du die NullPointerExceptions.
D.h. bau in dein JSP-Formular noch ein Textfeld ein oder pack den parseRequest-Aufruf in nen try-catch-Block rein.


----------



## Gumble (26. Aug 2005)

KSG9|plak hat gesagt.:
			
		

> 1. guckst du hier:
> 
> http://portals.apache.org/pluto/multiproject/pluto-portal/xref/org/apache/commons/fileupload/


Hab mir den source angeguckt - aber kann keine Schluesse daraus ziehen ???:L 


			
				KSG9|plak hat gesagt.:
			
		

> 2. dein formular muss ein Datei-Auswahl-Feld enthalten UND ein "normales" textfeld, sonst kriegst du die NullPointerExceptions.
> D.h. bau in dein JSP-Formular noch ein Textfeld ein oder pack den parseRequest-Aufruf in nen try-catch-Block rein.



Das versteh ich nicht - wieso ist das so und wo ist das dokumentiert? 
Mein jsp hat jetzt folgenden code:

```
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
[...]
<form method="POST" enctype="multipart/form-data" action="<portlet:actionURL/>">  
	<input type="text" name="textfeld"> 
	<input type="file">
	<input type="submit" value="Load"> 
</form>
```

es geht aber immer noch nicht (Selber fehler wie vorher) - was mach ich falsch? 

Noch mal die Frage von vorhin refreshen: verlinke nun die portlet.tld von der java-website. Ist das gute Stil oder sollte man eine ins jar-packen? Oder wie referenziere ich auf eine die in einer globalen Jar-Datei steckt?

@mod/admin
Vielleicht sollte man den Thread zerlegen und die Portlet-Geschichte separat abhandeln?


----------



## Gumble (28. Aug 2005)

Hat denn niemand ne Idee?  :roll: 
@KSG9|plak
wie sieht denn nun dein Protlet genau aus?


----------



## KSG9|sebastian (29. Aug 2005)

also die portlet.tld brauch bei jetspeed2 nicht im war-File sein, da sie beim deployen automatisch hinzugefügt wird.

Ich schau heut mittag mal genau nach wie mein Portlet aussieht.  Ich hab n Buch daheim, da steht das ganze auch drin...


----------



## KSG9|sebastian (29. Aug 2005)

```
so..hier das FileUploadPortlet:

public class FileUploadPortlet extends GenericPortlet{

   public static final String ERROR_NO_FILE = "ERROR_NO_FILE";

   public void doView(RenderRequest req, RenderResponse res) throws PortletException, IOException{
      res.setContentType("text/html");

      Writer w = res.getWriter();
      String error = req.getParameter("error");
      String size = req.getParameter("size");
      String contentType = req.getParameter("contentType");
      String serverFileName = req.getParameter("serverFileName");
      String param = req.getParameter("param");

      if(ERROR_NO_FILE.equals(error))
	w.write("expected to process an uploaded file.

");
      else if(error != null)
	w.write("Error: " + errors + "

");

      if(serverFileName != null){
	w.write("Filesize: " + size + "
");
	w.write("Content-Type: " + contentType + "
");
	w.write("Filename on Server: " + serverFileName + "
");
	w.write("Parameter: " + param);
      }
      PortletURL actionURL = res.createActionURL();

      w.write("<form method=post enctype=multipart/form-data action='" + actionURL.toString() + "'>");
      w.write("Upload File: <input type=file name=fileupload>
");
      w.write("Parameter: <input type=text name=param>
");
      w.write("<input type=submit></input></form>

   }
   public void processAction(ActionRequest req, ActionResponse res) throws PortletException, IOException{

      if(!PortletDiskFileUpload.isMultipartContent(req){
	res.setRenderParameteR("error", ERROR_NO_FILE);
	return;
      }
	
      PortletDiskFileUpload dfu = new PortletDiskFileUpload();

      dfu.setSizeMax(10 * 1000 * 1000);
      ddfu.setSizeThreshold(100 * 1000);

      try{
	List fileItems = dfu.parseRequest(req);
	Iterator iter = fileItems.iterator();

	while(iter.hasNext()){
	    FileItem item = (FileItem)iter.next();
	    if(item.isFormField()){
		String fieldName = item.getFieldName();
		String value = item.getName();
		res.setRenderParameter(fieldName, value);
	    } else{
		String fieldName = item.getFieldName();
		String fileName = item.getName();
		String contentType = item.getContentType();
		long size = item.getSize();
		res.setRenderParameter("size", Long.toString(size));
		res.setRenderParameter("contentType", contentType);

		String tmpdir = System.getProperty("java.io.tmpdir");
		String serverFileName = fieldName + "-portlet.tmp";
		res.setRenderParameter("serverFileName", serverFileName);
	    }
	}

      } catch(FileUploadException fue){
	fue.printStackTrace();
      }
   }
}
```

So, kann sein dass n paar Fehler drin sind! Ist nur abgetippt nicht reinkopiert


----------



## Gumble (29. Aug 2005)

wow danke fuer die Muehen!  :applaus: Welches Buch ist das? Gibt es bereits empfehlenswerte J2EE-Portal/Portlet-Buecher?


----------



## Gumble (29. Aug 2005)

Anscheinend gibts Probleme bei der Lib:
commons-fileupload-1.0.jar:
All Classes
DefaultFileItem
DefaultFileItemFactory
DeferredFileOutputStream
DiskFileUpload
FileItem
FileItemFactory
FileUpload
FileUploadBase
FileUploadBase.InvalidContentTypeException
FileUploadBase.SizeLimitExceededException
FileUploadBase.UnknownSizeException
FileUploadException
MultipartStream
ThresholdingOutputStream

commons-fileupload-1.1-dev.jar:
All Classes
DefaultFileItem
DefaultFileItemFactory
DiskFileItem
DiskFileItemFactory
DiskFileUpload
FileItem
FileItemFactory
FileUpload
FileUploadBase
FileUploadBase.InvalidContentTypeException
FileUploadBase.SizeLimitExceededException
FileUploadBase.UnknownSizeException
FileUploadException
MultipartStream
ParameterParser
PortletFileUpload
PortletRequestContext
RequestContext
ServletFileUpload
ServletRequestContext

Kriege folglich dein Beispiel so nicht zum laufen - du wirst ne jar haben die zeitlich zwischen den beiden Versionen liegt.


----------



## Gumble (29. Aug 2005)

Auch das Austauschen der common-io (v1.0 -> v.1.1-dev) im Ordner "D:\jboss-4.0.2\server\default\deploy\jboss-portal.sar\lib" hat nix gebracht. Hab naemlich in der Mailing-List gelesen dass fu1.1 auf io1.1 aufbaut.
Hier nochmal der Error:

java.lang.NullPointerException
        at org.apache.commons.fileupload.FileUploadBase.createItem(FileUploadBase.java:488)
        at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:359)
        at org.apache.commons.fileupload.portlet.PortletFileUpload.parseRequest(PortletFileUpload.java:101)
Hier Auszug aus den Sourcen: 

```
protected FileItem createItem(Map /* String, String */ headers,
                                  boolean isFormField)
        throws FileUploadException {
        return getFileItemFactory().createItem(getFieldName(headers),
                getHeader(headers, CONTENT_TYPE),
                isFormField,
                getFileName(headers));
    }
```
Hat jemand noch ne Idee? Oder eine alte, funktionierende jar?

EDIT: hab eine common-fileupload -jar unter "D:\jboss-4.0.2\server\default\deploy\jboss-portal.sar\lib" entdeckt. Dacht schon, juhu, das ist der Fehler. Also getauscht gegen die 1.1erDev, Cache geloescht und JBoss neustart: keine Aenderung 
Kleines OT: gibt es so eine Art Dependency-Walker unter Java? Moechte wissen ob auch die richtige Version des jars angezogen wurde.


----------



## KSG9|sebastian (29. Aug 2005)

ich benutz die commons-fileupload-1.0 und die funktioniert


----------



## Gumble (29. Aug 2005)

KSG9|plak hat gesagt.:
			
		

> ich benutz die commons-fileupload-1.0 und die funktioniert


Ich werde immer verwirrter ???:L hab nochmal das 1.0er runtergeladen, aber kompilieren meines Portlets geht nicht:  'PortletDiskFileUpload' kann nicht aufgeloest werden. Wenn man ins jar reinguckt ist auch kein passendes Class-File zu entdecken...


----------



## KSG9|sebastian (29. Aug 2005)

natürlich ist die Klasse nicht im Jar drin, deshalb sagte ich auch:

http://portals.apache.org/pluto/multiproject/pluto-portal/xref/org/apache/commons/fileupload/

Da findest du die Sourcen dazu!


----------



## Gumble (29. Aug 2005)

KSG9|plak hat gesagt.:
			
		

> natürlich ist die Klasse nicht im Jar drin, deshalb sagte ich auch:
> 
> http://portals.apache.org/pluto/multiproject/pluto-portal/xref/org/apache/commons/fileupload/
> 
> Da findest du die Sourcen dazu!


ooh ich Honk. Hab irgendwie nur den Rest mitgekriegt 'org/apache/commons/fileupload/' da dacht ich das waere die normale api-seite. 

Hab mich mal in das 1.1-dev reingehackt:

14:49:00,125 INFO  [STDOUT] [FileUploadBase] [createItem] getFileItemFactory():null
14:49:00,266 ERROR [CoreServlet] An error occured during the action request : null
java.lang.NullPointerException
        at org.apache.commons.fileupload.disk.DiskFileItem.getStoreLocation(DiskFileItem.java:534)
        at org.apache.commons.fileupload.disk.DiskFileItem.toString(DiskFileItem.java:600)
        at java.lang.String.valueOf(String.java:2577)
        at java.lang.StringBuilder.append(StringBuilder.java:116)
        at org.apache.commons.fileupload.FileUploadBase.createItem(FileUploadBase.java:505)
Da 'getFileItemFactory()' null liefert hab ich kurzum versucht selber eine DiskFileItemFactory anzulegen. Zuvor happerts aber - denke mal es liegt daran dass man nicht so einfach ein File anlegen darf. Also Security-maessig gesehn. Vielleicht schreib ich mal an die jakarta-common mailing list. Aber erstmal die pluto-version testen 

Danke nochmal, jetzt bin ich zuversichtlich dass es klappt.


----------



## Gumble (30. Aug 2005)

never ending story   
Also, die Pluto Files direkt ins Portlet reinkompiliert und comon-fileupload1.0 genommen:

09:59:14,010 INFO  [STDOUT] [processAction] item.getFieldName(): param
09:59:14,030 INFO  [STDOUT] [processAction] item.getName(): null
09:59:14,180 ERROR [CoreServlet] An error occured during the action request : value must not be null
java.lang.IllegalArgumentException: value must not be null
        at org.jboss.portal.server.util.Parameters.setParameter(Parameters.java:129)
        at org.jboss.portal.server.output.ActionResult.setRenderParameter(ActionResult.java:62)
        at org.jboss.portal.portlet.impl.ActionResponseImpl.setRenderParameter(ActionResponseImpl.java:160)
        at ***************.DefinitionOverViewPortlet.processAction(DefinitionOverViewPortlet.java:124)
Hier der dazugehoerige Code - sysos hab ich natuerlich nachtraeglich eingefuegt. Weiss naemlich noch nicht wie jboss-remote debugging geht bzw wills/kanns gar nicht testen da der Rechner hier total mies ist 

```
try {
			List fileItems = dfu.parseRequest(req);
			Iterator iter = fileItems.iterator();

			while (iter.hasNext()) {
				FileItem item = (FileItem) iter.next();
				if (item.isFormField()) {
					String fieldName = item.getFieldName();
					System.out.println("[processAction] item.getFieldName(): " + fieldName);
					String value = item.getName();
					System.out.println("[processAction] item.getName(): " + value);
					res.setRenderParameter(fieldName, value);
				} else {
```
Hmm, wieso ist 'value' null? und was sollte darin stehen?


----------



## Gumble (30. Aug 2005)

habs hingewurschtelt! Fuer diejenigen die es interessiert:

```
File foo = new File("/upload.tmp");
try {
	FileOutputStream fop = new FileOutputStream(foo);
	fop.write(item.get());
	fop.flush();
	fop.close();
} catch (Exception e) {
```
Das mach ich wenn das item _nicht_ isFormField() ist. Seltsamer weisse ist der Name der Items (getName()) im anderen Fall immer null. Also vom TextField und vom Button und genau das hat bei dem Codesample  die Exception geliefert. ???:L 
Ist vielleicht grundsaetzlich bei mir irgendwas falsch eingestellt?so ganz klar ist das mir naemlich alles nicht...


----------

