?
Solved

attachments in flex

Posted on 2011-02-14
5
Medium Priority
?
397 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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 1600 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

How To Reduce Deployment Times With Pre-Baked AMIs

Even if we can't include all the files in the base image, we can sometimes include some of the larger files that we would otherwise have to download, and we can also sometimes remove the most time-consuming steps. This can help a lot with reducing deployment times.

Question has a verified solution.

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

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…
In today's business world, data is more important than ever for informing marketing campaigns. Accessing and using data, however, may not come naturally to some creative marketing professionals. Here are four tips for adapting to wield data for insi…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses

770 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