Echo2FileTransferExample

The following example demonstrates how to build a simple Echo2-Application which makes use of the Echo2FileTransfer-Library to upload and download files.


You can download a complete .war-file with sources and current build of the Echo2FileTransfer-Library for direct deployment into your application server here: [WWW] http://jfix.org/echo/FileTransferDemo.war


First of all we need a simple WEB-INF/web.xml to get started. Just the usual stuff, nothing fancy to see.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

    <display-name>FileTransferDemo</display-name>
    
    <servlet>
      <servlet-name>FileTransferDemo</servlet-name>
      <servlet-class>FileTransferDemoServlet</servlet-class>
    </servlet>

    <servlet-mapping>
      <servlet-name>FileTransferDemo</servlet-name>
      <url-pattern>/</url-pattern>
    </servlet-mapping>
        
</web-app>

That was easy... next we have to create the default application-servlet. Just create a Java-file in the default-package as FileTransferDemoServlet.java.

import nextapp.echo2.app.ApplicationInstance;
import nextapp.echo2.webcontainer.WebContainerServlet;

public class FileTransferDemoServlet extends WebContainerServlet {        
    public ApplicationInstance newApplicationInstance() {
        return new FileTransferDemo();
    }
}

And now we can build the main-application. For keeping things simple, all required code is put into the file below. In a real application you would seperate concerns more carefully, but its good to keep things simple for educational purposes.

Besides a small init() which just creates a column to hold the components, there are three interesting parts:

Please see comments below to see how to wire things up correctly.

Create a Java-file in the default-package as FileTransferDemo.java.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.TooManyListenersException;

import nextapp.echo2.app.ApplicationInstance;
import nextapp.echo2.app.Button;
import nextapp.echo2.app.Column;
import nextapp.echo2.app.ContentPane;
import nextapp.echo2.app.Window;
import nextapp.echo2.app.event.ActionEvent;
import nextapp.echo2.app.event.ActionListener;
import nextapp.echo2.app.filetransfer.Download;
import nextapp.echo2.app.filetransfer.DownloadProvider;
import nextapp.echo2.app.filetransfer.UploadEvent;
import nextapp.echo2.app.filetransfer.UploadListener;
import nextapp.echo2.app.filetransfer.UploadSelect;

/**
 * Simple demo which shows how to transfer files with Echo2.
 * 
 * This demo allows every user to upload files to the system-wide tmp-directory
 * and to download these files again within the session.
 * 
 * This is just an simple example how to use the Echo2-FileTransfer-Library. It
 * is not intended for production use in any way!
 * 
 * Please take appropriate means to secure your application when allowing users
 * to upload content to your server.
 * 
 * @author Maik Jablonski
 */
public class FileTransferDemo extends ApplicationInstance {

    /**
     * Creates a column with an upload-selection.
     */
    public Window init() {
        Column column = new Column();
        column.add(getUploadSelect());

        ContentPane contentPane = new ContentPane();
        contentPane.add(column);

        Window window = new Window();
        window.setContent(contentPane);

        return window;
    }

    /**
     * Delivers an upload-selection and creates a download-button for each uploaded
     * file.
     */
    private UploadSelect getUploadSelect() {
        UploadSelect uploadSelect = new UploadSelect();
        try {
            uploadSelect.addUploadListener(new UploadListener() {
                public void fileUpload(UploadEvent uploadEvent) {
                    try {
                        // Read out the content of the uploaded file.
                        byte[] b = new byte[uploadEvent.getSize()];
                        uploadEvent.getInputStream().read(b, 0,
                                uploadEvent.getSize());

                        // Save content to disk via a FileWrapper.
                        FileWrapper file = new FileWrapper();
                        file.setName(uploadEvent.getFileName());
                        file.setType(uploadEvent.getContentType());
                        file.setContent(b);

                        // Add a download-button for uploaded file
                        ((UploadSelect) uploadEvent.getSource()).getParent()
                                .add(getDownloadButton(file));
                    } catch (IOException ioe) {
                        // Urgs... do something nicely to inform the user.
                        ioe.printStackTrace();
                    }
                }

                public void invalidFileUpload(UploadEvent uploadEvent) {
                    // Clean up if something went wrong...
                }
            });
        } catch (TooManyListenersException e) {
            // Don't register more than one listener...
        }
        return uploadSelect;
    }

    /**
     * Delivers a simple Download-Button for a given FileWrapper.
     * 
     * The Download-Button has an ActionListener, which handles the download of
     * a file when clicked. Therefore a DownloadProvider must be created,
     * activated and enqueued as command to the application.
     */
    private Button getDownloadButton(final FileWrapper file) {
        Button button = new Button(file.toString());
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                Download download = new Download();
                download.setProvider(new DownloadProvider() {
                    public String getContentType() {
                        return file.getType();
                    }

                    public String getFileName() {
                        return file.getName();
                    }

                    public int getSize() {
                        return (int) file.getSize();
                    }

                    public void writeFile(OutputStream stream)
                            throws IOException {
                        stream.write(file.getContent());
                    }
                });
                download.setActive(true);
                enqueueCommand(download);
            }
        });
        return button;
    }
}

/*
 * FileWrapper which stores content in a tmp-file.
 * 
 * This is just an example and should be replaced by your own implementation
 * depending on your real-storage.
 */
class FileWrapper {

    private String name;

    private String type;

    private String path;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    /**
     * Retrieves content from tmp-file.
     */
    public byte[] getContent() throws IOException {
        File file = new File(path);
        byte[] content = new byte[(int) file.length()];
        FileInputStream inputStream = new FileInputStream(file);
        inputStream.read(content);
        inputStream.close();
        return content;
    }

    /**
     * Stores content in a tmp-file.
     * 
     * The current milliseconds are used as a "semi-unique" prefix for
     * the temporary file. This works usually fine for demonstration
     * purposes without much concurrency. Please use a synchronized
     * "real" unique sequence for production use.
     */
    public void setContent(byte[] content) throws IOException {
        File tmpFile = File.createTempFile(String.valueOf(System
                .currentTimeMillis()), null);
        // Play nicely and delete files when the application stops...
        tmpFile.deleteOnExit();        
        path = tmpFile.getCanonicalPath();
        FileOutputStream outputStream = new FileOutputStream(tmpFile);
        outputStream.write(content);
        outputStream.close();
    }

    public long getSize() {
        return new File(path).length();
    }

    public String toString() {
        return name + " (" + type + ")" + " [" + getSize() / 1024 + " KB]"; 
    }
}

Now you'll can start your container and visit the page via http://localhost:8080/.


Spanish Version

last edited 2007-10-10 19:19:49 by mjablonski