First, I’d would to thanks DJDaveMark for his translation of my french post.


To upload more than one file to a server in one go without having to zip them all up, there are two solutions :

  • Java Applet
  • Flash

I’ve chosen to show you an example which uses Stripes and SWFUpload
logostripes.pngminnelli_logo.png

I use the IDE Eclipse. An explanation of Eclipse is not my goal here, as I am assuming everything here is familiar to everyone. I also use the Maven2 plugin for Eclipse.

Creation of the project pom.

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.fullsix</groupId>
    <artifactId>demo</artifactId>
    <packaging>war</packaging>
    <name />
    <version>0.0.1-SNAPSHOT</version>
    <description />
    <build>
        <finalName>demo</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <configuration>
                    <contextPath>/</contextPath>
                    <connectors>
                        <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                            <port>8080</port>
                        </connector>
                    </connectors>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.stripes</groupId>
            <artifactId>stripes</artifactId>
            <version>1.4.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.4</version>
        </dependency>
    </dependencies>
</project>

Here’s the web.xml :

<?xml version="1.0" encoding="ISO-8859-1" ?>
<web-app id="Communautaire_Front" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>SWF Upload</display-name>

    <filter>
        <display-name>Stripes Filter</display-name>
        <filter-name>StripesFilter</filter-name>
        <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
        <init-param>
            <param-name>ActionResolver.UrlFilters</param-name>
            <param-value>classes</param-value>
        </init-param>
        <init-param>
            <param-name>ActionResolver.PackageFilters</param-name>
            <param-value>com.fullsix.demo.action.*</param-value>
        </init-param>
        <init-param>
            <param-name>MultipartWrapper.Class</param-name>
            <param-value>net.sourceforge.stripes.controller.multipart.CommonsMultipartWrapper</param-value>
        </init-param>
        <init-param>
            <param-name>FileUpload.MaximumPostSize</param-name>
            <param-value>500m</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>StripesFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

    <filter-mapping>
        <filter-name>StripesFilter</filter-name>
        <servlet-name>StripesDispatcher</servlet-name>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

    <servlet>
        <servlet-name>StripesDispatcher</servlet-name>
        <servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>StripesDispatcher</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

    <!-- The Usual Welcome File List -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

Here’s the Stripes action :

package com.fullsix.demo.action;

import java.io.File;
import java.io.IOException;

import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.Before;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.FileBean;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.controller.StripesRequestWrapper;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
 *
 * @author Damien Viel 
 * @version $Id$
 *
 */
@UrlBinding(”/upload.action”)
public class UploadActionBean implements ActionBean {

    private static final Log logger = LogFactory.getLog(UploadActionBean.class);
    private ActionBeanContext context;
    private FileBean filedata;

    @SuppressWarnings(”unused”)
    @Before(LifecycleStage.BindingAndValidation)
    private void rehydrate(){
        String filename = getContext().getRequest().getParameter(”Filename”);

        if (StringUtils.isNotEmpty(filename)){
            StripesRequestWrapper req = (StripesRequestWrapper)getContext().getRequest();
            filedata = req.getFileParameterValue(”Filedata”);
        }
    }

    public ActionBeanContext getContext() {
        return this.context;
    }

    public void setContext(ActionBeanContext context) {
        this.context = context;
    }

    @DefaultHandler
    public Resolution upload() {
        if (filedata!=null){
            try {
                filedata.save(new File(filedata.getFileName()));
            } catch (IOException e) {
                logger.error(”Error while writing file :” + filedata.getFileName());
            }
        }
        return new ForwardResolution(”/success.jsp”);
    }
}

SP Creation

To keep it simple, I’ve used the source code from the SWFUpload “simpleExample”.


<%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="stripes"%>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>SWFUpload Demos - Simple Demo</title>
<link href="css/swf.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="swfupload/swfupload.js"></script>
<script type="text/javascript" src="js/swfupload.queue.js"></script>
<script type="text/javascript" src="js/fileprogress.js"></script>
<script type="text/javascript" src="js/handlers.js"></script>
<script type="text/javascript">
		var swfu;

		window.onload = function() {
			var settings = {
				flash_url : "swfupload/swfupload_f9.swf",
				upload_url: "http://localhost:8080/upload.action",	// Relative to the SWF file
				post_params: {"Test" : "coucou"},
				file_size_limit : "100 MB",
				file_types : "*.*",
				file_types_description : "All Files",
				file_upload_limit : 100,
				file_queue_limit : 0,
				custom_settings : {
					progressTarget : "fsUploadProgress",
					cancelButtonId : "btnCancel"
				},
				debug: false,

				// The event handler functions are defined in handlers.js
				file_queued_handler : fileQueued,
				file_queue_error_handler : fileQueueError,
				file_dialog_complete_handler : fileDialogComplete,
				upload_start_handler : uploadStart,
				upload_progress_handler : uploadProgress,
				upload_error_handler : uploadError,
				upload_success_handler : uploadSuccess,
				upload_complete_handler : uploadComplete,
				queue_complete_handler : queueComplete	// Queue plugin event
			};

			swfu = new SWFUpload(settings);
	     };
	</script>
</head>
<body>

<div id="content">
	<h2>Simple Demo</h2>
<stripes:form beanclass="com.fullsix.demo.action.UploadActionBean" id="form1">

	<p>This page demonstrates a simple usage of SWFUpload.  It uses the Queue Plugin to simplify uploading or cancelling all queued files.</p>

			<fieldset class="flash" id="fsUploadProgress">
			<legend>Upload Queue</legend>
			</fieldset>
		<div id="divStatus">0 Files Uploaded</div>
			<div>
				<input type="button" value="Upload file (Max 100 MB)" onclick="swfu.selectFiles()" style="font-size: 8pt;" />
				<input id="btnCancel" type="button" value="Cancel All Uploads" onclick="swfu.cancelQueue();" disabled="disabled" style="font-size: 8pt;" />
			</div>

	</stripes:form>
</div>
</body>
</html>

A zip file of the eclipse project is available here -> stripes-swfupload.zip