Solved

attachments in flex

Posted on 2011-02-14
5
378 Views
Last Modified: 2012-05-11
hi guys
I am new to flex. Did anyone work with attachments in flex? I need to let the user attach files, and once the screen is submitted i want the attachment files to be sent to backend( java backend)
Any ideas how i can do that?

thanks.
0
Comment
Question by:royjayd
  • 3
  • 2
5 Comments
 
LVL 20

Expert Comment

by:ChristoferDutz
ID: 34892702
What technology are you using for your Backend? Spring? Are you using BlazeDS, Webservices or raw http-communication to communicate with the backend.
0
 

Author Comment

by:royjayd
ID: 34893065
spring blazeDS
0
 
LVL 20

Expert Comment

by:ChristoferDutz
ID: 34895139
Ok ... same setup I am using :)

At first you have to use a FileReference object in your Flex client:
http://livedocs.adobe.com/flex/3/html/17_Networking_and_communications_7.html

With this you have two options:
1. You Load the data of the file into your flex application and send it to the server as byte-Array.
2. You Upload the data of the file to the server using HTTP Multiplart Request.

I would certainly stick to option 2 as in Option 1 BlezeDS will not create a byte[] for your data but a Byte[] which is insanely larger than a simple byte-array.

I used option 2 by setting up spring MVC and create a controller and view for uploading files:
Here's the controller:
import de.upw.ps.ucg.attachments.AttachmentService;
import de.upw.ps.ucg.attachments.model.Attachment;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Iterator;
import java.util.UUID;

/**
 * Created by IntelliJ IDEA.
 * User: cdutz
 * Date: 17.02.2010
 * Time: 21:15:20
 */
public
class AttachmentUploadController
        implements Controller, InitializingBean
{
    private AttachmentService attachmentService;

    private File attachmentsHomePath;

    //////////////////////////////////////////////
    // Spring setters.
    //////////////////////////////////////////////

    @Required
    public
    void setAttachmentsService(final AttachmentService aAttachmentService)
    {
        attachmentService = aAttachmentService;
    }

    @Required
    public void setAttachmentsHomePath(File attachmentsHomePath) {
        this.attachmentsHomePath = attachmentsHomePath;
    }

    //////////////////////////////////////////////
    // Spring lifecycle methods.
    //////////////////////////////////////////////

    @Override
    public void afterPropertiesSet() throws Exception {
        if(!attachmentsHomePath.exists()) {
            if(!attachmentsHomePath.mkdirs()) {
                throw new Exception("Could not create attachment-directory specified by " +
                        "attachmentsHomePath property. '" + attachmentsHomePath.getAbsolutePath() +
                        "'");
            }
        }
        if(!attachmentsHomePath.isDirectory()) {
            throw new Exception("attachmentsHomePath must point to a directory. '" +
                    attachmentsHomePath.getAbsolutePath() + "'");
        }
    }

    //////////////////////////////////////////////
    // Controller methods.
    //////////////////////////////////////////////

    @Override
    public
    ModelAndView handleRequest(final HttpServletRequest aHttpServletRequest,
                               final HttpServletResponse aHttpServletResponse)
            throws Exception
    {
        final String fileName = aHttpServletRequest.getParameter("fileName");
        if(fileName != null) {
            final MultipartHttpServletRequest mpHttpRequest = (MultipartHttpServletRequest) aHttpServletRequest;
            final Iterator<String> fileParameterNames = mpHttpRequest.getFileNames();
            while(fileParameterNames.hasNext()) {
                final String fileParameterName = fileParameterNames.next();
                final MultipartFile file = mpHttpRequest.getFile(fileParameterName);

                final String id = saveAttachment(file);
                if(id != null) {
                    final Attachment attachment = new Attachment();
                    attachment.setId(id);
                    attachment.setFileName(fileName);
                    attachment.setAdditionDate(Calendar.getInstance());

                    attachmentService.createAttachment(attachment);

                    return new ModelAndView("attachmentView", "attachment", attachment);
                }
            }
        }
        return null;
    }

    private String saveAttachment(MultipartFile file) {
        // Generate a new Id for the attachment.
        final UUID id = UUID.randomUUID();

        // To limit the number of files in one directory, the hash of the id is used
        // to partition the files into 32 containers.
        final int containerId = Math.abs(id.hashCode()) % 32;
        final File containerPath = new File(attachmentsHomePath, Integer.toString(containerId));
        if(!containerPath.exists()) {
            if(!containerPath.mkdirs()) {
                throw new RuntimeException("Could not create container-path '" +
                        containerPath.getAbsolutePath() + "'");
            }
        }

        // Save the file to the attachment directory.
        final File attachmentPath = new File(containerPath, id.toString());
        try {
            file.transferTo(attachmentPath);
        } catch (IOException e) {
            throw new RuntimeException("Error saving attachment to attachment directory. '" +
                    attachmentPath.getAbsolutePath() + "'");
        }

        return id.toString();
    }
}

Open in new window

The view:
/**
 * Created by IntelliJ IDEA.
 * User: cdutz
 * Date: 17.02.2010
 * Time: 21:28:56
 */
public
class AttachmentView
        extends AbstractView
{
    private static final SimpleDateFormat isoDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

    public AttachmentView() {
        setContentType("application/octet-stream");
    }

    @Override
    @SuppressWarnings("unchecked")
    protected
    void renderMergedOutputModel(final Map map,
                                 final HttpServletRequest httpServletRequest,
                                 final HttpServletResponse httpServletResponse)
            throws Exception
    {
        if(map.containsKey("attachment")) {
            final Attachment attachment = (Attachment) map.get("attachment");
            httpServletResponse.getOutputStream().write(("attachmentId=" +
                    attachment.getId() + "\n").getBytes());
            httpServletResponse.getOutputStream().write(("attachmentFileName=" +
                    attachment.getFileName() + "\n").getBytes());
            httpServletResponse.getOutputStream().write(("attachmentAdditionDate=" +
                    isoDateFormat.format(attachment.getAdditionDate().getTime()) + "\n").getBytes());
        }
        else if(map.containsKey("file")) {
            final Map<String, Object> model = (Map<String, Object>) map.get("model");
            final Attachment attachment = (Attachment) model.get("attachment");
            final File attachmentFile = (File) model.get("file");
            if((attachment != null) && (attachmentFile != null)) {
                setContentType("application/octet-stream");
                final byte[] attachmentData = getBytesFromFile(attachmentFile);
                httpServletResponse.getOutputStream().write(attachmentData);
            }
        }
    }

    protected
    byte[] getBytesFromFile(final File aFile)
    {
        byte[] bytes = null;
        InputStream is = null;
        try {
            is = new FileInputStream(aFile);

            // Get the size of the file
            final long length = aFile.length();
            if (length < Integer.MAX_VALUE) {
                // Create the byte array to hold the data
                bytes = new byte[(int)length];

                // Read in the bytes
                int offset = 0;
                int numRead;
                while (offset < bytes.length
                       && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
                    offset += numRead;
                }
            }
        } catch (final FileNotFoundException e) {
            e.printStackTrace();
        } catch (final IOException e) {
            e.printStackTrace();
        } finally {
            // Close the input stream and return bytes
            try {
                if(is != null) {
                    is.close();
                }
            } catch (IOException e) {
                // Well ... I guess we can't do anything against this, can we?
            }
        }

        return bytes;
    }
}

Open in new window

And the spring configuration:
    <!--
        Dispatch requests to components registered by the
        BeanNameUrlHandlerMapping class.
    -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--
        View resolver used connect the views returned by
        controllers to view implementation classes
    -->
    <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
    <!--
        Enable multipart message handling.
    -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- the maximum file size in bytes (Set to 100MB) -->
        <property name="maxUploadSize" value="100000000"/>
    </bean>
    <!--

        MVC Definitions

    -->
    <bean name="/attachment-upload.html" class="de.upw.ps.ucg.attachments.mvc.AttachmentUploadController">
        <property name="attachmentsService" ref="attachmentsService"/>
        <property name="attachmentsHomePath" value="${ucg.home}${file.separator}attachments"/>
    </bean>
    <bean id="attachmentView" class="de.upw.ps.ucg.attachments.mvc.AttachmentView"/>

Open in new window


I hope I didn't miss anything. Good luck.

0
 

Author Comment

by:royjayd
ID: 34896423
So the flex ui calls the spring view? I am trying to understand the flow.
Thanks.
0
 
LVL 20

Accepted Solution

by:
ChristoferDutz earned 400 total points
ID: 34896461
Not really ...
The Flex Client uploads the file to a http-url. The spring MVCController intercepts this and ueses the BeanNameUrlHandlerMapping to identify the controller by matching the url-suffix to a bean name (in my case it was "/attachment-upload.html"). The CommonsMultipartResolver is needed or Spring MVC will not be able to handle Multipart requests and all you could access was the name of the uploaded file. The controller is then executed and it returns a string representing which view it would like to display the result. The BeanNameViewResolver then uses this string to lookup a bean with the id matching this string (in my case "attachmenView".

Hope you get the idea ... it's a pretty tricky setup, it took me about one week to have everything up and running, but now it works great and if I follow my setup-template it's easy to reproduce.
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Adobe X Reader 6 340
FlashBuilder allocate more memory using FlashBuilder.ini 18 248
Adobe indesign suite cs5.5   How to enable "indesign" capability? 2 189
Indesign Data Merge 1 181
First things first - Preparation We need all the part for this install and it's much nicer to have them all on hand when you need them so here's what's required. Download Eclipse 3.5 32 bit (I like the Classic flavour) from here. (http://www.e…
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.

914 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now