FileUpload server-side example

7,921 views
Skip to first unread message

Dave

unread,
May 18, 2008, 11:00:31 PM5/18/08
to Google Web Toolkit
I have been trying to use the FileUpload widget. The client-side code
does not seem terribly difficult, especially since an example of it is
supplied in the FileUpload javadocs. But I am clueless as to how to
write the server-side code that actually reads the file that was
uploaded. I found this:

http://home.izforge.com/index.php/2006/10/29/295-handling-file-uploads-with-the-google-web-toolkit

but that approach appears to conflict with the instructions for
handling RPC calls to the server given in the GWT RPC documentation
and here:

http://www.ibm.com/developerworks/web/library/os-ad-gwt3/

In particular, the GWT documentation and the latter article indicate a
specific pattern to following for making RPC calls that involves
creating two interfaces (a synchronous and an asynchronous version)
and an implementation class, and the client code makes the RPC call by
calling the method(s) declared in the asynchronous interface. However,
the former article, which describes how to upload a file using GWT's
FileUpload widget, does something entirely different. I'm sure that
the code given there is the simplest and easiest cakewalk in the world
for web developers, but I am not one of those and so it makes no sense
to me, since I so far know nothing about servlets, etc. other than
what I have read in the latter article above and on the GWT website,
which make no mention of "HttpServlet" or "doPost" or any of the other
incantations from the former article.

Could someone please show a simple, but complete, example of the
server-side code (and necessary html and xml changes, etc.) that would
be needed to complete the example given in GWT's FileUpload javadoc,
using the "canonical" way of making RPC calls in GWT? Or, if the
canonical "make two interfaces and a class" way of doing things does
not apply with FileUpload, can someone please show an example of what
actually must be done on the server to read the file once it is sent
to the server, or point me to a resource that explains in elementary
terms what is going on in the server-side example of the former
article?

Thank you.

Dave

Jason Morris

unread,
May 19, 2008, 3:12:03 AM5/19/08
to Google-We...@googlegroups.com
Hi Dave,

The first link there:

http://home.izforge.com/index.php/2006/10/29/295-handling-file-uploads-with-the-google-web-toolkit

is what you do want to look at. As for a simple explanation:

Because of browser security restrictions, GWT has no way to load a file into an
RPC call. So: you can't use GWT RPC to send a file to the server. What we do
instead is use a "traditional" HTML form to submit the file.

So something link this:

FormPanel form = new FormPanel();
// if the form is in GET mode, you can't send files
form.setMethod(FormPanel.METHOD_POST);
// instead of sending traditional HTTP parameters (in a query string)
// we are sending files, which are very different beasts.
// *An important note:* any other objects implementing HasName will
// also be sent to the server if they are added to the FormPanel
// but their values will be sent as "FileItem"s (in Commons-FileUpload terms)
// and cannot be fetched using the normal HttpServletRequest.getParameter
// method.
form.setEncoding(FormPanel.ENCODING_MULTIPART);
// finally we need to tell the Form which /servlet/ it must submit to
// this is much like the ServiceEntryPoint, however, it must point
// to a normal HttpServlet instead of a RemoteServiceServlet
form.setTarget(GWT.getModuleBaseURL() + "uploads.target");

FormPanel is a SimplePanel (and so only accepts a single Widget as a child), so
you'll want to add your FileUpload widget (and any labels and such) to another
Panel, and then add that to the FormPanel.

When you want to submit the file to the server, you use FormPanel.submit();
which is sort of like making an RPC call.

On the server side of things, because this is (like I said earlier) a
"traditional" HTML form, you need a normal HttpServlet to handle it, because
there is no RPC body.

You will need to give all of your fields that are attached under the FormPanel
names (using setName(String)) so that the HttpServlet can identify them (see
FileItem.getFieldName()).

Hope this helps ;)

Dave

unread,
May 19, 2008, 4:40:45 PM5/19/08
to Google Web Toolkit
Thank you for your help. Combined with the website I mentioned earlier
(which was incomplete and does not work exactly as described, though
it is close), I have figured out how to do this. Here are the complete
(I think) instructions for anyone else attempting to do this:

Obtain and install
- GWT (I have version 1.4)
- Eclipse (I have version 3.3)
- Cypal Studio for GWT (I have version RC5)
- The Eclipse plugins needed for Cypal (WPT and some others, I think)
- commons-fileupload and commons-io (as described here:
http://home.izforge.com/index.php/2006/10/29/295-handling-file-uploads-with-the-google-web-toolkit)

In Eclipse, go to Window->Preferences->Cypal Studio and set the GWT
home to be the directory where you installed GWT.

Create a new Dynamic Web Project named UploadFile.

Right-click on the project and go to Properties->Java Build Path-
>Libraries->Add External Jars. Add the files commons-fileupload.jar
and commons-io.jar, which should be contained in the download for each
of those libraries.

Right-click on the project and select New Cypal Studio Module. Name
the module UploadFile, and put it in the package uploadfile.

Right-click on the project and select New Servlet. Name the servlet
UploadFileServlet, and put it in the package uploadfile.

The previous two steps take care of adjusting *most* of the proper xml
files for you, but to work with GWT in hosted mode, you must add the
line
<servlet path="/UploadFileServlet"
class="uploadfile.server.UploadFileServlet"/>
inside the module tag of the file UploadFile.gwt.xml.

Paste the following code into UploadFile.java:


package uploadfile.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FormHandler;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormSubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormSubmitEvent;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class UploadFile implements EntryPoint {

public void onModuleLoad() {
// Create a FormPanel and point it at a service.
final FormPanel uploadForm = new FormPanel();
uploadForm.setAction(GWT.getModuleBaseURL() +
"UploadFileServlet");

// Because we're going to add a FileUpload widget, we'll need to
set the
// form to use the POST method, and multipart MIME encoding.
uploadForm.setEncoding(FormPanel.ENCODING_MULTIPART);
uploadForm.setMethod(FormPanel.METHOD_POST);

// Create a panel to hold all of the form widgets.
VerticalPanel panel = new VerticalPanel();
uploadForm.setWidget(panel);

// Create a FileUpload widget.
FileUpload upload = new FileUpload();
upload.setName("uploadFormElement");
panel.add(upload);

// Add a 'submit' button.
Button uploadSubmitButton = new Button("Submit");
panel.add(uploadSubmitButton);

uploadSubmitButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
uploadForm.submit();
}
});

uploadForm.addFormHandler(new FormHandler() {
public void onSubmit(FormSubmitEvent event) {
}

public void onSubmitComplete(FormSubmitCompleteEvent event) {
Window.alert(event.getResults());
}
});

RootPanel.get().add(uploadForm);
}

}


This is essentially the example from the javadoc for the FileUpload
widget, with the setAction method (Jason: setTarget does not appear to
be a method in FormPanel; perhaps you are thinking of another class?)
corrected to erase a warning you will get in hosted mode, and with the
setName method called on the FileUpload object in order to allow the
servlet later to identify the FileUpload object.

Paste the following code into UploadFileServlet:


package uploadfile.server;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
* Servlet implementation class for Servlet: UploadFileServlet
*/
public class UploadFileServlet extends HttpServlet implements Servlet
{

private static final long serialVersionUID = 8305367618713715640L;

protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/plain");

FileItem uploadItem = getFileItem(request);
if (uploadItem == null) {
response.getWriter().write("NO-SCRIPT-DATA");
return;
}

byte[] fileContents = uploadItem.get();
//TODO: add code to process file contents here. We will just print
it.
System.out.println(new String(fileContents));
response.getWriter().write(new String(fileContents));
}

private FileItem getFileItem(HttpServletRequest request) {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);

try {
List items = upload.parseRequest(request);
Iterator it = items.iterator();
while (it.hasNext()) {
FileItem item = (FileItem) it.next();
if (!item.isFormField()
&& "uploadFormElement".equals(item.getFieldName())) {
return item;
}
}
} catch (FileUploadException e) {
return null;
}
return null;
}
}


This is essentially the code from
http://home.izforge.com/index.php/2006/10/29/295-handling-file-uploads-with-the-google-web-toolkit,
but with the expression
"uploadFormElement".equals(item.getFieldName()) altered to be
consistent with the line upload.setName("uploadFormElement").

If you run this from Eclipse in hosted mode and upload a text file,
you should see the contents of the file in a pop-up window (between
pre tags for some reason), and the servlet will print the contents of
the file to the standard output console in Eclipse, which corresponds
to the two statements after the //TODO comment.

Dave

Carl Scott

unread,
May 19, 2008, 9:57:26 PM5/19/08
to Google Web Toolkit
This is where not using RPC at all really comes in handy, it takes out
the need for the extra work/additional layers. Anyway, I'd just note
for this two things:

1) I had the extra tag problem too. Setting the content type to text/
html may work better for you if you are returning tagged content, but
you may or may not have to escape html characters (I don't think you
do, though). That just returned me the content itself, no extra tag
included. Content type text/xml went to hell in a handbag.
2) Your implementation will limit you to uploading only one file at a
time. Fine if this is specific to this project but you'll probably
end up using that code again at some point in another project.

--
Carl Scott
Software Developer, Solertium Corporation

On May 19, 4:40 pm, Dave <pexa...@gmail.com> wrote:
> Thank you for your help. Combined with the website I mentioned earlier
> (which was incomplete and does not work exactly as described, though
> it is close), I have figured out how to do this. Here are the complete
> (I think) instructions for anyone else attempting to do this:
>
> Obtain and install
> - GWT (I have version 1.4)
> - Eclipse (I have version 3.3)
> - Cypal Studio for GWT (I have version RC5)
> - The Eclipse plugins needed for Cypal (WPT and some others, I think)
> - commons-fileupload and commons-io (as described here:http://home.izforge.com/index.php/2006/10/29/295-handling-file-upload...)
> This is essentially the code fromhttp://home.izforge.com/index.php/2006/10/29/295-handling-file-upload...,

Sebastian Quiles

unread,
Jun 30, 2008, 11:18:49 AM6/30/08
to Google Web Toolkit
I followed thoses rules as close as I could, but I have a little
problem and no clue on how to solve it. My problem is that at this
point:

List items = upload.parseRequest(request);

the resulting list (items) is empty, regardless if I'm sending or not
the file.

here is my code:
client side:
------------------------------------------------
final FormPanel form = new FormPanel();
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setMethod(FormPanel.METHOD_POST);
form.addStyleName("table-center");
form.addStyleName("demo-FormPanel");

Label lb = new Label("Select file");
FileUpload upload = new FileUpload();

VerticalPanel holder = new VerticalPanel();
holder.add(lb);
holder.add(upload);

holder.add(new Button("Import", new ClickListener(){
public void onClick(Widget sender) {
form.submit();
}
}));

form.add(holder);
panel.add(form);

form.setAction(GWT.getModuleBaseURL() + "ImportItems");

form.addFormHandler(new FormHandler(){
public void onSubmit(FormSubmitEvent event) {
panel.add(new Label("hi"));
}

public void onSubmitComplete(FormSubmitCompleteEvent event) {
panel.add(new Label("bye"));
Window.alert(event.getResults());
}
});
-------------------------
and the server side:
-------------------------
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// Check that we have a file upload request (got this line from the
net, not using it by the moment)
boolean isMultipart = ServletFileUpload.isMultipartContent(request);

response.setContentType("text/plain");

FileItem uploadItem = getFileItem(request);
if (uploadItem == null) {
response.getWriter().write("NO-SCRIPT-DATA");
return;
}
//byte[] fileContents = uploadItem.get();
response.getWriter().write(new String(uploadItem.get()));
}

private FileItem getFileItem(HttpServletRequest request){
FileItemFactory factory = new DiskFileItemFactory();
// Set factory constraints
//factory.setSizeThreshold(yourMaxMemorySize);
//factory.setRepository(yourTempDirectory);

ServletFileUpload upload = new ServletFileUpload(factory);
//upload.setSizeMax(yourMaxRequestSize);

try {
List items = upload.parseRequest(request);
Iterator it = items.iterator();
while (it.hasNext()) {
FileItem item = (FileItem) it.next();
if (!item.isFormField() && "upload".equals(item.getFieldName())){
return item;
}
}
} catch (FileUploadException e){
return null;
}
return null;
}
-----------------------------

I suppose the configuration in the .gwt.xml is ok because the flow
control execute the doPost method.
the result of senfing a file is:
x) the "hi" label is printed
x) the doPost method is executed
x) the List items = upload.parseRequest(request) returns an epmty
list
x) as consequence, the getFileItem returns null
x) as consequence, the client receives "No-Script DATA" message
x) and the Bye label is printed

Sebastian Quiles

unread,
Jun 30, 2008, 1:21:40 PM6/30/08
to Google Web Toolkit
don't need a reply, I've found the problem:

in the client side, I didn't set the name of the component with:
upload.setName("upload")

Neophyte

unread,
Jul 1, 2008, 4:46:33 AM7/1/08
to Google Web Toolkit
Thanks you for these comprehensive posts. I have been trying to get a
fileUpload to work properly for a while now and now it finally worked,
however.... (I hate that word)...
1) When I upload anything other then a .txt file looks like it wants
to make HTML out of it (try uploading your .project file for
instance).
2) When I upload, I get the dialog box twice, and every time after I
upload, I get it one extra time. Where does this behaviour come from
and how to fix it?

With regards, Patrick

PS: I it happends with both Dave and Sebastians code.
PPS: I use GWT 1.5 RC1 with FF 3 RC1 should it matter.

Kurposkano

unread,
Jul 8, 2008, 4:00:17 PM7/8/08
to Google Web Toolkit
Mine is doing the same thing of calling the
onSubmitComplete(FormSubmitCompleteEvent event) method many times.
Also, I need to make it stop trying to turn everything into an HTML
file as I am sending back XML and this screws it up. Anyone know how
to do this? I can make it so it sends it back as a downloadable file
but I just need it to be a string containing the exact XML from before
and nothing more than that.

Kurposkano

unread,
Jul 8, 2008, 6:53:57 PM7/8/08
to Google Web Toolkit
I've gotten it so that you don't get the weird HTML anymore. The way
it is set up, the event expects it to be HTML so there is no way
around that. Instead, what you have to do is create a new HTML object
with the event.getResults() as the input for the constructor of the
new HTML. Then you call getText() on that HTML and you have your
String (if a string is what you were sending back, it was for me).
I've used this method to upload a file to my upload server, return it
as a string, and then send that string to my RPC server so that it
could be used there as was intended.

Ron Lawrence

unread,
Aug 29, 2008, 3:29:10 PM8/29/08
to Google Web Toolkit

FYI all, you can use the same RPC servlet to handle the file upload,
simply override "service" in the RPC servlet, then handle the file
upload as shown in the examples above. In the case where it's not
multipart, or there is no uploaded file, just call super to keep the
RPC framework happy.

You will also need to set your form's action with
formPanel.setAction( GWT.getModuleBaseURL() + "Servletname" ); use the
same servlet name that's in your module's or web.xml file.

@Override
protected void service( HttpServletRequest request,
HttpServletResponse response ) throws ServletException,
IOException
{
boolean isMultipart = ServletFileUpload.isMultipartContent( new
ServletRequestContext(
request ) );
if ( isMultipart )
{
FileItem uploadItem = getFileItem( request );
if ( uploadItem == null )
{
super.service( request, response );
return;
}

response.setContentType( "text/plain" );
byte[] fileContents = uploadItem.get();
// verify the file here....
String myFile = new String(fileContents);
if (myFile.contains( "xxxx" ))
{
//do stuff with the data....
response.getWriter().write( "OK" );
}
else
{
response.getWriter().write( "Invalid file");
}
}
else
{
super.service( request, response );
}
}

private FileItem getFileItem( HttpServletRequest request )
{
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload( factory );
upload.setSizeMax( 10000000 );

try
{
List<FileItem> items = upload.parseRequest( request );
for ( FileItem item : items )
{
if ( !item.isFormField()
&& "upload".equals( item.getFieldName() ) )
{
return item;
}
}
}
catch ( FileUploadException e )
{
return null;
}
return null;
}
Message has been deleted

Madz

unread,
Aug 31, 2008, 11:53:59 PM8/31/08
to Google Web Toolkit
Hi,

I try your code and it give me this errors when I hit the upload
button.

[INFO] <H1>HTTP Status 500 - </H1>
<HR noShade SIZE=1>

<P><B>type</B> Exception report</P>
<P><B>message</B> <U></U></P>
<P><B>description</B> <U>The server encountered an internal error ()
that prevented it from fulfilling this request.</U></P>
<P><B>exception</B> <PRE>javax.servlet.ServletException: Servlet
execution threw an exception
</PRE>
<P></P>
<P><B>root cause</B> <PRE>java.lang.StackOverflowError
sun.nio.cs.ISO_8859_1$Encoder.encodeArrayLoop(Unknown Source)
sun.nio.cs.ISO_8859_1$Encoder.encodeLoop(Unknown Source)
java.nio.charset.CharsetEncoder.encode(Unknown Source)
java.lang.StringCoding$StringEncoder.encode(Unknown Source)
java.lang.StringCoding.encode(Unknown Source)
java.lang.String.getBytes(Unknown Source)

org.apache.commons.fileupload.FileUploadBase.getBoundary(FileUploadBase.java:
409)
org.apache.commons.fileupload.FileUploadBase
$FileItemIteratorImpl.&lt;init&gt;(FileUploadBase.java:929)

org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:
331)

org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:
349)

org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:
126)

com.driftmark.ui.server.FileUploadImpl.getFileItem(FileUploadImpl.java:
63)
com.driftmark.ui.server.FileUploadImpl.doPost(FileUploadImpl.java:28)
javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
com.driftmark.ui.server.FileUploadImpl.doPost(FileUploadImpl.java:31)

</PRE>
<P></P>
<P><B>note</B> <U>The full stack trace of the root cause is available
in the Apache Tomcat/5.0.28 logs.</U></P>
<HR noShade SIZE=1>

<H3>Apache Tomcat/5.0.28</H3>


On Aug 30, 3:29 am, Ron Lawrence <RonLawren...@gmail.com> wrote:
> FYI all, you can use the same RPC servlet to handle thefileupload,
> simply override "service" in the RPC servlet, then handle thefileuploadas shown in the examples above. In the case where it's not
> multipart, or there is no uploadedfile, just call super to keep the
> RPC framework happy.
>
> You will also need to set your form's action with
> formPanel.setAction( GWT.getModuleBaseURL() + "Servletname" ); use the
> same servlet name that's in your module's or web.xmlfile.
>
>   @Override
>   protected void service( HttpServletRequest request,
>     HttpServletResponse response ) throws ServletException,
> IOException
>   {
>     boolean isMultipart = ServletFileUpload.isMultipartContent( new
> ServletRequestContext(
>       request ) );
>     if ( isMultipart )
>     {
>       FileItem uploadItem = getFileItem( request );
>       if ( uploadItem == null )
>       {
>         super.service( request, response );
>         return;
>       }
>
>       response.setContentType( "text/plain" );
>       byte[] fileContents = uploadItem.get();
>       // verify thefilehere....
>       String myFile = new String(fileContents);
>       if (myFile.contains( "xxxx" ))
>       {
>         //do stuff with the data....
>         response.getWriter().write( "OK" );
>       }
>       else
>       {
>         response.getWriter().write( "Invalidfile");
>       }
>     }
>     else
>     {
>       super.service( request, response );
>     }
>   }
>
>   private FileItem getFileItem( HttpServletRequest request )
>   {
>     FileItemFactory factory = new DiskFileItemFactory();
>     ServletFileUploadupload= new ServletFileUpload( factory );
>    upload.setSizeMax( 10000000 );
>
>     try
>     {
>       List<FileItem> items =upload.parseRequest( request );

Supriya...@gmail.com

unread,
Sep 2, 2008, 6:41:08 AM9/2/08
to Google Web Toolkit
Hi! We are new to GWT and i have some issue coming up with accessing
server servlet from client code.

I am running compiled GWT code using Jdeveloper 10.1.3.3

Client code gives me the proper interface but when i click on submit
to upload the file, then server code comes into picture and it gives
me error like:-
<h1>404 Not Found</h1>Resource
*********servlet not found on this server

Please please help me!!!!!!!!!!!!!!!!!!!!

Ron Lawrence

unread,
Sep 2, 2008, 12:12:31 AM9/2/08
to Google Web Toolkit
I am using gwt 1.4.62, and the approach of overriding 'service' is
working great for my RPC servlet. I am uploading csv files without any
issue. From the stack trace, it looks like you are handling the
upload from the "doPost" method rather than from "service". Maybe that
is the difference.

Ron Lawrence

unread,
Sep 2, 2008, 12:12:31 AM9/2/08
to Google Web Toolkit
I am using gwt 1.4.62, and the approach of overriding 'service' is
working great for my RPC servlet. I am uploading csv files without any
issue. From the stack trace, it looks like you are handling the
upload from the "doPost" method rather than from "service". Maybe that
is the difference.

On Aug 31, 9:53 pm, Madz <markdie...@gmail.com> wrote:

Supriya Aggarwal

unread,
Sep 4, 2008, 10:35:02 AM9/4/08
to Google-We...@googlegroups.com
Hey thanks a lot for replying! But can uploading be done using RPC?? I thot we have to just use HTTP servlet for that!

-Supriya

Supriya Aggarwal

unread,
Sep 5, 2008, 2:41:05 AM9/5/08
to Google-We...@googlegroups.com

Hey thanks a lot for replying! But i wanted to clarify that in web mode do we need to access client and server classes or it is managed just by all the generated html and css??


-Supriya


On Tue, Sep 2, 2008 at 9:42 AM, Ron Lawrence <RonLaw...@gmail.com> wrote:

Sumit Chandel

unread,
Sep 8, 2008, 11:59:53 AM9/8/08
to Google-We...@googlegroups.com
Hi Supriya,

I'm not completely sure what you mean by whether an application needs to access client and server classes in web mode, but I think your question is where the separation is between your GWT client code and your server-side Java code in the deployed web environment.

As you might have imagined it, the GWT compiler generates JavaScript, HTML and applies any CSS rules you've used from your GWT client code. In web mode, these are the resources that you need to deploy to serve the client browser to load up your application. The server-side code must be deployed on the web server as well but is uniquely run on the server-side. To properly deploy your server-side code you'll need to include the compiled .class files as well as any JARs containing the binary for other libraries you are using.

As for the problem you are facing with the 404 response when trying to upload a file to the File Upload Servlet, it seems very likely to be that the path you're uploading to isn't the same as the one you've mapped to your File Upload servlet in your web.xml file. Double-check to see where the request is going in the file upload (a number of different HTTP traffic watchers are available and should help in this regard) and match the patch to the one you have defined in your web.xml file.

Hope that helps,
-Sumit Chandel
Reply all
Reply to author
Forward
0 new messages