Solved

attachments in flex

Posted on 2011-02-14
5
375 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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

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…
Is your company's data protection keeping pace with virtualization? Here are 7 dynamic ways to adapt to rapid breakthroughs in technology.
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

762 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

19 Experts available now in Live!

Get 1:1 Help Now