Everyone has had the experience of uploading images to a web site. You are given a set of 10 browse buttons and have to select each file you want to upload, or worse have to go back to the same page over and over again and select each file. Most applications provide a nice drag and drop interface which allows you to easily select multiple images (as well as other files) and add them to your documents.
This article demonstrates a simple and easy way to let users of your website drag and drop files from their file system and upload them to your server. In addition to being easier for your users to use, this program will zip all the files into one archive for faster uploading. This program is a sample application with full source code, allowing you to customize and integrate this functionality into your own web application.
This application has two parts: a Java applet and a Java servlet. You could achieve similar functionality using Internet Explorer and an ActiveX control, but Java is the only multi-browser cross-platform option available today. This sample will run on Windows, Linux, MacOS, and any other platform where Java is available. Most computers already have a Java JDK installed, but if you don’t have one you can download it from http://www.javasoft.com.
A version of this application with PHP on the server is available on the Panyasan’s Random Musings. This version replaces the Java servlet with a PHP script and include some good enhancements to the Java applet.
The code in this application is free and is released under the Apache 2.0 license. That means you are welcome to use, copy, and change this code as much as you would like. If you find any bugs, have any comments, or make any improvements I would love to hear from you. There are a couple of other programs needed to run this sample, but they are all free.
Setup
source code
Get the Source Code
You should start by downloading the source code for this sample. It can be found here.
Get Other Programs
This program has been setup to be built using Apache Ant. Ant is a very popular build tool for Java projects. Building this project without Ant is possible, but it can be tricky to set up all the pieces. If you don’t have Ant already you should download and install it..
This program will generate a WAR file which requires a servlet container to run. It should work with any J2EE compliant server. I use Jetty, an open source web server. It is light, fast, and free.
Build and Run
Once you have installed Ant and Jetty you can build and run the sample application by following these steps:
- Unzip the
samplesarchive to a directory on your machine. - Open a command prompt and change directories to the location you unzipped the sample in.
- Execute the command
ant(you may need to provide the full path to your Ant installation). - Copy the WAR file
dist/dnddemo.warto thewebappsdirectory of your Jetty server. - Start the Jetty server. (The start command is
java -jar start.jar.) - Open a browser and go to http://localhost:8080/dnddemo/imageadd.htm. This URL will be different if you use a different server.
Core Technologies
This program will use the following core technologies:
- Java Applets
- Java Servlets
- Signed JARs
- Drag and Drop
- HTTP
- Java Swing
- Java IO
This example will demonstrate a Java applet contained in a signed JAR and using drag and drop, a Java servlet, simple HTTP connections, a basic Java Swing based application, and use of the Java Input/Output libraries.
How It Works
This program consists of a servlet and a signed applet. The servlet will accept files being uploaded to the server and the applet will provide those files. The applet must be signed because it will need to access files on the user’s machine.
This program is completely browser-based. It can be accessed with the following URL: http://localhost:8080/dnddemo/imageadd.htm. This page will show a warning the first time it is run.

This warning appears because the applet is not signed by a certificate authority. This applet was signed locally as part of the build process. This will be discussed more in the section about building the application. You can run this applet safely since you have just built it, but you should always read messages like this carefully and never run applications from sources you do not trust.
Once you choose to run this applet you will see the drag and drop applet demo image uploader.

You can drag images (as well as other files) from your desktop or any other location on your computer and drop them on the label at the top of the applet. Once you have dropped all of the files you want, press the upload button to send those files to the server.
When you press the upload button the applet will gather all of the selected files and add them to a zipped archive. It will then transmit that zip archive to the servlet. The servlet will read the archive and save each file to a directory on the server. The servlet will then display the list of images that have been uploaded and allow you to view them in your browser.
Let’s Look at the Code
This application consists of two files DNDApplet.java and ImageSrv.java. The DNDApplet is responsible for gathering the files and uploading them to the server. The ImageSrv is responsible for receiving those files and then displaying them back to the user.
DNDApplet.java
DNDApplet.java extends java.applet.Applet and implements DropTargetListener. Extending the applet class allows our class to run in the bowser and implementing drop target listener interface allows our class to accept drag and drop gestures. This allows the class to operate inside the browser and accept drag and drop events from programs outside of the browser. Let’s take a look at the code to handle drag and drop.
The first step is to register our control as a drop target. This will let Java know that our control is a valid place to drop items that are dragged from somewhere else. That code is part of the init method and it looks like this:
JLabel title = new JLabel("Drag and Drop Files Here");
DropTarget dt = new DropTarget(title, this);
|
This code snippet will tell Java that the label is a drop target and that this class will handle the drag and drop events generated by that action. This is why DNDApplet implements DropTargetListener.
Registering as a DropTargetListener will generate events when the user drags over your target, enters your target, exits your target, and finally drops on your target. We are only interested in the drop event. The code behind that event is very simple. Let’s take a look:
public void drop(DropTargetDropEvent dtde)
{
int action = dtde.getDropAction();
dtde.acceptDrop(action);1
fromTransferable(dtde.getTransferable());2
dtde.dropComplete(true);3
}
|
1. Accept the drop action.
2. Get the data from the drop event.
3. Notify the JVM that the drop event has been completed so it can clear the drag and drop event with the native operating system.
That is all it takes. Now let’s take a look at the basics of getting the data from the drop event. The full code for this method can be found in DNDApplet.java in the sample code.
private void fromTransferable(Transferable t)
{
DataFlavor flavors[] = t.getTransferDataFlavors();1
if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)2) {
List list = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
m_fileList.addAll(list);3
StringBuffer sb = new StringBuffer();
sb.append("<HTML><UL>");
for (int i = 0; i < m_fileList.size(); i++) {
File f = (File) m_fileList.get(i);
sb.append("<LI>" + f + "</LI>\n");
}
sb.append("</UL></HTML>");4
m_statusLabel.setText(sb.toString());
m_updload.setEnabled(true);5
}
}
|
We will start by getting all of the data flavors from the drop event1.. A drag and drop event can originate from any program on your machine. The data associated with the event could be in any of a large number of formats. The source of a drag and drop event may offer multiple flavors of data, allowing the drop target to pick the one that best suits its needs. These data flavors will be defined by the source of the drag and drop even. For example, a drag and drop of a piece of text from OpenOffice might provide one data flavor containing just the selected text and another data flavor containing the full formatting information. This is the same mechanism used to support copy, cut, and paste between different applications.
This application is interested in the javaFileListFlavor2. type. When we see this flavor, we know that the user is dragging one or more files onto our applet. The data in the drag and drop event will be a list of the files. We can then add these files to our list of files to upload to the server3.. Once we have added the files to the list we want to display those files to our users. We can take advantage of the HTML support in JLabels to produce some nice formatting when we add each file to the list4.. Finally we enable the upload button5. so the user can start the upload process.
ImageSrv.java
When the user presses the upload button the ImageSrv will be contacted. ImageSrv is an HttpServlet and it handles uploading and displaying the files from the applet. Files are uploaded to the servlet using an HTTP PUT request. This is a request just like the one that comes from browsers – it will not cause problems with firewalls and proxy servers. Let’s take a look at a simplified version of the doPut method. The full version can be found in ImageSrv.java in the sample code.
public void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
ZipInputStream in = new ZipInputStream(request.getInputStream());1
File dir = new File("webapps/dnddemo/images");
dir.mkdirs();2
try {
while (true) {
ZipEntry entry = in.getNextEntry();
if (entry == null) {
break;3
}
File f = new File(dir, entry.getName());
FileOutputStream out = new FileOutputStream(f);
try {
int read;
byte[] buf = new byte[1024];
while ((read = in.read(buf)) > 0) {
out.write(buf, 0, read);4
}
} finally {
if (out != null) {
out.close();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
in.close();
}
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("%lt;html>%lt;head>%lt;title>ImageSrv%lt;/title>%lt;/head>%lt;/html>");
out.flush();
out.close();5
response.setStatus(HttpServletResponse.SC_OK);6
}
|
1. The applet has provided all the uploaded files as a zip archive. We need to read the files out of the archive and write them to the server’s local file system.
2. We need to make sure the directory exists before we start adding files to it.
3. When we hit the end of the zip file the next entry will be null.
4. Write out each file to the file system, 1024 bytes at a time.
5. Return a response to the applet so it knows that the files are done uploading.
6. Return a response code of OK to indicate that everything was successful.
Once we have uploaded the files to the server we want to display them to the user. The servlet will show a list of all the files as well as showing each file. The servlet uses an HTTP parameter to determine which image to show. For example you can see a list of all the files at this address:
http://localhost:8080/dnddemo/imageview.htm
You can display a specific image using this address, replacing “image1.jpg” with your image’s filename:
http://localhost:8080/dnddemo/imageview.htm?image=image1.jpg
Let’s take a look at a simplified version of the doGetImage method. The doGetImage method is responsible for delivering images and other files to the browser. The full version can be found in ImageSrv.java in the sample code.
public void doGetImage(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String image = request.getParameter("image");
if (image.endsWith(".jpg")) {
response.setContentType("image/jpeg");
} else if (image.endsWith(".gif")) {
response.setContentType("image/gif");
} else if (image.endsWith(".png")) {
response.setContentType("image/png");
} else {
response.setContentType("application/binary");1
}
readFile(image, response.getOutputStream());2
}
|
When a web server returns a file to a browser it also includes a mime type. The mime type or content type lets the browser know how to handle a file from the server. Most servlets use the content type of text/html to indicate that their response is in HTML format. When we return images and other files we need to set the appropriate content type. This method will supply the correct content type for JPG, GIF, and PNG files. For all other files we return a content type of application/binary1.. This content type tells the browser that this a generic binary file. The browser will most likely prompt the user to save the file rather than trying to display it. Once we have set the correct content type we can send the actual bytes of the file down to the browser2..
There is a useful reference list of mime types available at http://www.w3schools.com/media/media_mimeref.asp.
How it Gets Built
Most Java applications are built in two steps: a compiler creates Java class files from the Java source code, and then a build program like ant packages the class files into JARs, WARs, and other archives. This program requires the additional step of signing the applet JAR. The warning message displayed when running the applet is because this JAR was signed with a certificate authority meant only for testing. If you sign this applet with a certificate from an established certificate authority like VeriSign you will not see this warning message.
Building and Signing the JAR
A set of Java classes can be put together in a JAR (Java ARchive) and delivered as a single application. Normally a JAR file consists of the files needed to run the application and a manifest file that describes the JAR file. Most applets are packaged in JAR files to allow faster downloading and better code organization.
Applets run inside a special applet security manager. This security manager restricts the actions code within the applet can take and protects your computer from malicious code. Applets are generally not allowed to read files from your local file system. Our applet requires extra permission to do so. In order to gain that extra permission our applet JAR must be signed.
Signing a JAR will ensure that it was really written by the person or group who says they wrote it and that the code has not been changed since it was signed. The most common way to do this is to use a certificate authority. The developer of the application can obtain a certificate of authenticity from the certificate authority. This certificate can be presented along with the application to ensure the validity of the application.
Creating a valid certificate takes more time and money than is reasonable for a sample application. This application will use a certificate authority meant just for testing. This is why you will see the warning mentioned earlier when you load the applet.
The signed portion of this application will look like this:
Signature-Version: 1.0 SHA1-Digest-Manifest-Main-Attributes: 4mBNxPp0vnlZ33Hos81NvtUDJQk= Created-By: 1.6.0_01 (Sun Microsystems Inc.) SHA1-Digest-Manifest: 1O/wwDSPkGFPLrSI+0gStTLxld0= Name: dndapplet/applet/DNDApplet.class SHA1-Digest: Sq7jYIN9MvZ87IONaokNDB9MK7U= |
There will also be an additional section added to the JAR’s manifest file which will look like this:
Name: dndapplet/applet/DNDApplet.class SHA1-Digest: awxXry4+saVToZprtEbntMnCbTI= |
As part of the build process for this application a key store will be created. This key store will hold the private part key used to sign this application. This key store will then be used to sign the applet JAR file. There are more comments and specific steps about this process in the build.xml file included with this sample.
For more information about signed JARs you can see the documentation for the jarsigner tool included with the Java Development Environment. It can be found at http://java.sun.com/javase/6/docs/technotes/tools/windows/jarsigner.html.
A Note About Security
This sample will allow users to take files from their computers and post them to a directory on your server. This is a potentially dangerous thing to allow. You have no way of knowing if the file being posted is a harmless image or a malicious script file. You should always make sure that the permissions for user files you store on your server specify that the files cannot be run on your server. You might also consider storing the files in a database instead.
Conclusion
Providing a good user experience is vital to the success of your application. Extending the drag and drop metaphor of the desktop to the browser is a great way to make your application easy to use. You can add a real certificate to this applet and use it in production very quickly.
This application has been made simple for demonstration purposes and can easily be expanded. You can take this sample and adapt it to your web application. You could also add progress bars, better error handling, or whatever features you can imagine. There is also much more information, comments, and sample code in the source archive for this sample.
{ 31 comments… read them below or add one }
Thank you Zack for this code. I have made heavy use of it here
Christian
Thanks for the effort ,nice code
Hi,
Thanks for your code it helps me a lot, is it possible to drag the email items from outlook and drop it on applet so that it can save the email item on server. Is this requirement doable using java.
Appreciate your effort
Thanks
Venkat
Hello Venkat,
I’m not sure what mimetype Outlook uses for mail message. You should add a few System.out.println calls to the applet and give it a try. If the mimetype is reasonable then it will work here.
-Zack
Looking for example web sites uising this code, please send URL thanks
Hi,
I’m trying to implement panyasan’s version of this code in my web project. I’ve got it set up and ready, but when I try to upload files I keep getting “cannot retry due to server authentication, in streaming mode”. I am confused about what authentication the error message is referring to. My programming skills is limited to some javascript and php, I’ve never done anything in java before. Do you have any suggestions?
Kind regards,
Anders
Hello Anders,
It is tough to diagnose without a lot more details, but it sounds like your server is requiring authentication to upload the files. You could put some prints into your PHP code and see if it is even being called. My suspicion is that it isn’t.
If my suspicion is correct you should look at your server settings. Either you need to change your settings to allow the uploads anonymously, or you need to add authentication to the Java applet. Good luck.
-Zack
And you have a full upload applet here with same features: JFileUpload
Hi there
I had a go at this, but without luck.
I can build, install and get the interface with the applet showing in my browser as described above.
When I try do drop files I run into problems. Two popup’s appear, the first one whit the text;
df: java.awt.datatransfer.DataFlavor[mimetype=text/uri-list;representationclass=java.io.Reader]the next one showing:
t.getTransferData(df): java.io.InputStreamReader@9e8c34Any hints are welcome!
best regards
John
This message indicates that the data flavor of the drag and drop event isn’t recognized. When you drop something in you get a data flavor to indicate what type of thing you are dragging and dropping. What operating system are you using?
At the moment I’m trying with Fedora 10 on the server side.
Clients running Firefox on CentOS (
2.6.9-78.0.13), Ubuntu (2.6.24-19) and Fedora 10 (2.6.27.21-170.2.56.fc10.x86_64).I’m using Jetty as described, but previously I’ve tried with Apache with similar result.
I’ve tried to drop all sorts of filetypes, but with the same result
I’m afraid I’m not much of an Java wizz …
John
Hello John,
The client operating system is what matters for this issue since the applet isn’t even trying to talk to the server at the point you see the message. I have never tried this program on CentOS. The file type of java.io.InputStreamReader means you are getting an input stream to read something out of. You might try reading the stream contents and seeing what they are. They might be the file name or a copy of the file itself.
There is a sample of reading from streams in Java here: http://java.sun.com/docs/books/tutorial/i18n/text/stream.html. Good luck.
hi,
How to add a thumbnail option for images…
Thanks,
prathap
Hello Prathap.
Thank you very much for your comment. This sample does not have the ability to show a thumbnail, but adding it isn’t too difficult. You have access to the data file references for the image in the fromTransferable method.
On line 340 we get the file. You could change the code here to load the data from the image and display a thumbnail. There is an example of the code you need here: http://www.java2s.com/Tutorial/CSharp/0480__2D/ThumbnailImageCreation.htm.
Good luck and please let us know if you get it working.
hi zack,
Thank you very much for your answer…ya i got the example code, but i didn’t understand this sentence. “On line 340 we get the file”.
i am using Apache tomcat 5.5 . where i can change the code C:\Program Files\Apache Software Foundation\Tomcat 5.5\webapps\dnddemo or C:\dnd
each time i need to rebuild ..?
Wait for your replay
hi zack,
Thank you very much for your answer…ya i got the example code, but i didn’t understand this sentence. “On line 340 we get the file”.
i am using Apache tomcat 5.5 . where i can change the code C:\Program Files\Apache Software Foundation\Tomcat 5.5\webapps\dnddemo or C:\dnd
each time i need to rebuild ..?
Waiting for your replay
Hello Prathap,
If you look at line 340 of DNDApplet.java you’ll see a line that says
File f = (File) m_fileList.get(i);. This line is part of the applet and it runs on the client machine. You want to change the code here and then rebuild and redeploy to your Tomcat environment.Hope this helps,
Zack
Hi Zack,
Thanks you very much for your support.
Thanks.
prathap
Hi Zack,
How to Increase memory limit of file upload….ex: files which are more then 25 mb its not uploading. Please help me in this.
Thanks,
prahtap
Hello Prahtap,
There is no specified file size limit and I have tested this with files over 100 megabytes. It sounds like you may have run into a specific configuration issue.
Are you getting an error message from the client or your server? What web server are you using? If you put some debug prints in the servlet does the file get there at all?
Hope this helps,
Zack
Hi zack,
Thanks for your replay, actually i am using Tomcat 5.5 and i tried to upload images 0f 100mb, but its not shown any error message.
Its uploading file size below 26 mb perfectly.
Thanks,
prathap
I’ve tried this with Jetty, but not Tomcat. I do know that Tomcat by default uses a relatively low heap size. This sample places the uploaded images into memory and you may just be running out of memory on your server. You can try increasing your heap size by changing the memory settings in your catalina.bat or catalina.sh file. You want to change the JAVA_OPTS and add a maximum memory size. It looks like this:
JAVA_OPTS=’-Xmx256M’
Good luck,
Zack
is it possible to drag the item from outlook and drop it here. outloog mime type is
application/vnd.ms-outlook. please let me know.
Hello Upender,
The current program does not support Microsoft Outlook. However, this application is open source and a good example of handling mimetypes in Java. It shouldn’t take very long to experiment and make it work. If you do please let us know.
I hope this helps.
Firefox 3.6 has added native support for drag’n drop uploading using JavaScript. I wrote an article about it with a demo http://www.thecssninja.com/javascript/drag-and-drop-upload
Ryan,
This is very cool. Thank you for sharing. Web applications are really starting to catch up with desktop applications.
Hello Zack,
I am Calling Outlook COM using your native code and the problem is when I drag mail item from outlook and drop it on applet, then it removing the mail item from outlook. is there any way to avoid this problem.
Thanks
Hello Upender,
I don’t think I understand your question. This applet is all Java and does not contain any native code. It also doesn’t provide a way to call Outlook or any other product using the COM interface. Can you please tell me a little more about what you are trying to do and your set up. Thanks.
I am really sorry for that , I am integrated open source native code to your classes for calling COM methods.
I’m a flash actionscript programmer and a pro at html/xtml and im pretty good at taking pieces and parts of other peoples java,php,actionscript,ajax, ect.. source and modifying it for my needs but when it comes to object oriented programming and compiling and using libraries and classes I have alot of trouble comprehending it im just wondering if perhaps its possible that im just not capable of doing it or does it just take a long time to learn? I have big dreams concerning this program you have made but i lack the means
Object-oriented programming takes a little while to get used to. Maybe you could try a book. Grady Booch has some excellent object-oriented programming books. Good luck.