[ DWR Website | Web Application Index ]

# Asynchronous FileUpload

This is an example of uploading files via DWR

- Demo
- How it works
- Source

Please select an image and a text file for uploading. A simple transform will take the image a scale it to 200 pixels square, and emboss on it the text from the uploaded file.

Image: |
File: |
Color: | #

DWR automatically converts files from the browser to instances of `org.directwebremoting.export.FileUpload` using the "file" converter. When you click on the Upload button the browser calls the `uploadFiles()` function, which simply gets the values from the 3 input elements and passes them up to DWR:

    function uploadFiles() {
      var image = dwr.util.getValue('uploadImage');
      var file = dwr.util.getValue('uploadFile');
      var color = dwr.util.getValue('color');

      FileUploader.uploadFiles(image, file, color, function(data) {
        dwr.util.setValue('image', data);
      });
    }

`dwr.util.getValue()` is a utility to get the value of any element, in this case a file object.

On the server, DWR calls the `FileUploader.uploadFiles()` Java method, which has the following signature:

    BufferedImage uploadFiles(BufferedImage uploadImage, String uploadFile, String color)

Transform the image by scaling it and writing the text onto the image

    uploadImage = scaleToSize(uploadImage);
    uploadImage = grafitiTextOnImage(uploadImage, uploadFile, color);
    return uploadImage;

And that's basically it. See the full source for how to resize using an AffineTransform and write text onto an image, it's got nothing to do with DWR, so we can skip it for now. The Java code returns the image which DWR converts and passes it to the callback in the JavaScript which simply updates the image in the web page:

    dwr.util.setValue('image', data);

The really good news is that 99% of this code is about image manipulation. The DWR part is trivially easy.

## HTML source:

        <table>
          <tr>
            <td>Image</td>
            <td><input type="file" id="image" /></td>
            <td id="image.container">&nbsp;</td>
          </tr>
          <tr>
            <td>File</td>
            <td><input type="file" id="file" /></td>
            <td id="file.container">&nbsp;</td>
          </tr>
          <tr>
            <td colspan="3">
              <button onclick="uploadFilesFlat()">Save Flat</button>
              <button onclick="uploadFilesNested()">Save Nested</button>
            </td>
          </tr>
        </table>

## Javascript source:

    function uploadFiles() {
      var image = dwr.util.getValue('uploadImage');
      var file = dwr.util.getValue('uploadFile');
      var color = dwr.util.getValue('color');

      FileUploader.uploadFiles(image, file, color, function(data) {
        dwr.util.setValue('image', data);
      });
    }

## Java source:

    /**
     * A demonstration of uploading files and images
     * @author Joe Walker [joe at getahead dot ltd dot uk]
     */
    public class FileUploader
    {
        /**
         * Take 2 uploaded files and return an image based on them
         * @param uploadImage The uploaded image
         * @param uploadFile The uploaded file
         * @param color The selected color
         * @return A mangled image based on the 2 uploaded files
         */
        public BufferedImage uploadFiles(BufferedImage uploadImage, String uploadFile, String color)
        {
            uploadImage = scaleToSize(uploadImage);
            uploadImage = grafitiTextOnImage(uploadImage, uploadFile, color);

            return uploadImage;
        }

        /**
         * Voodoo to scale the image to 200x200
         * @param uploadImage The image to work on
         * @return The altered image
         */
        private BufferedImage scaleToSize(BufferedImage uploadImage)
        {
            AffineTransform atx = new AffineTransform();
            atx.scale(200d / uploadImage.getWidth(), 200d / uploadImage.getHeight());
            AffineTransformOp afop = new AffineTransformOp(atx, AffineTransformOp.TYPE_BILINEAR);
            uploadImage = afop.filter(uploadImage, null);
            return uploadImage;
        }

        /**
         * And scrawl the text on the image in 10 rows of 20 chars
         * @param uploadImage The image to work on
         * @param uploadFile The text to write on the image
         * @param color The selected color
         * @return The altered image
         */
        private BufferedImage grafitiTextOnImage(BufferedImage uploadImage, String uploadFile, String color)
        {
            while (uploadFile.length() < 200)
            {
                uploadFile += uploadFile + " ";
            }

            Graphics2D g2d = uploadImage.createGraphics();
            for (int row = 0; row < 10; row++)
            {
                String output = null;
                if (uploadFile.length() > (row + 1) * 20)
                {
                    output = uploadFile.substring(row * 20, (row + 1) * 20);
                }
                else
                {
                    output = uploadFile.substring(row * 20);
                }

                g2d.setFont(new Font("SansSerif", Font.BOLD, 16));
                g2d.setColor(ColorUtil.decodeHtmlColorString(color));
                g2d.drawString(output, 5, (row + 1) * 20);
            }

            return uploadImage;
        }
    }