Link to home
Start Free TrialLog in
Avatar of Jay Roy
Jay RoyFlag for United States of America

asked on

attachments in flex

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.
Avatar of ChristoferDutz
ChristoferDutz
Flag of Germany image

What technology are you using for your Backend? Spring? Are you using BlazeDS, Webservices or raw http-communication to communicate with the backend.
Avatar of Jay Roy

ASKER

spring blazeDS
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.

Avatar of Jay Roy

ASKER

So the flex ui calls the spring view? I am trying to understand the flow.
Thanks.
ASKER CERTIFIED SOLUTION
Avatar of ChristoferDutz
ChristoferDutz
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial