Image upload component for OpenLaszlo with drag & drop support and preview

336 Views Asked by At

I haven't seen any good file upload component for OpenLaszlo. Is there an open source version of a file upload component, which supports drag & drop for DHTML and Adobe AIR, and a preview functionality for both runtimes?

Technically it is possible to support the following features:

  • drag and drop file upload in DHTML for all desktop browsers http://caniuse.com/#feat=dragndrop
  • preview of images for Webkit browsers and Firefox in DHTML, and for all browsers using a SWF runtime
  • drag and drop support for Adobe Air applications

Maybe someone has an existing component which could be made open source, and maintained or improved by the community.

1

There are 1 best solutions below

5
On BEST ANSWER

There is currently no way to do a File Upload in DHTML (aka HTML5) mode of an OpenLaszlo application since unfortunately there is no way to set the form type to enctype=multipart/form-data in that run-time.

However, you can do a File Upload with the SWF(Flash) mode of an OpenLaszlo application by accessing the low-level Flash API. It is not obvious how to do this so I wrote a class to do this myself a while back, it will work under (Flash) SWF8, SWF9 and SWF10 mode of OpenLaszlo.

I have never tried compiling an OpenLaszlo application to AIR but I believe the Flash Upload will probably work for that case too.

Here is my class, feel free to use it:

( The code is also avaiable here: http://forum.openlaszlo.org/showthread.php?t=14566&highlight=fileReference )

<library>

<switch>

  <when property="$as3"><!-- SWF9/SWF10 -->

    <!---
    CLASS: <fileuploadhelper>
    EXTENDS: <node> (lz.node)

    DESCRIPTION:

    This is the ActionScript3 (AS3) (SWF9/SWF8) version of the Flash file
    upload object.

    This allows users to upload files when compiled to a Flash Version that
    uses ActionScript3 such as Flash 9 or Flash 10.
    -->
    <class name="fileuploadhelper" extends="node">

      <!---
      @param string uploadurl: (optional) default upload url to use if none
                               passed to this.upload()
      -->
      <attribute name="uploadurl" type="string" />

      <!-- @keywords private -->
      <!--- @param flash.net.FileReference file_reference: Flash file reference object -->
      <attribute name="file_reference" type="expression" value="null" />

      <!-- Imports Required for SWF9/SWF10 -->

      <passthrough>
        import flash.net.FileReference;
        import flash.events.Event;
        import flash.events.ProgressEvent;
        import flash.events.IOErrorEvent;
        import flash.events.SecurityErrorEvent;
        import flash.net.URLRequest;
      </passthrough>

      <!-- *** METHODS *** -->

      <handler name="oninit">
      <![CDATA[

        #passthrough  {
           this.file_reference = new FileReference();

           file_reference.addEventListener(Event.SELECT,this.onSelect);
           file_reference.addEventListener(Event.COMPLETE, this.onComplete);
           file_reference.addEventListener(ProgressEvent.PROGRESS, this.progressHandler);
           file_reference.addEventListener(IOErrorEvent.IO_ERROR, this.ioErrorHandler);
           file_reference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.securityErrorHandler);

        }#

      ]]>
      </handler>

      <!---
      Displays file browsing window and allows the user to select a file (or
      cancel to close the window).
      -->
      <method name="browse">
      <![CDATA[

        #passthrough  {
           file_reference.browse();
        }#

      ]]>
      </method>

      <!---
      Return name of selected file

      @returns string: the filename of the selected file
      -->
      <method name="getName">
        return this.file_reference.name;
      </method>

      <!--- @keywords private -->
      <!---
      @param string submit_url: SWF9/10 #passthrough{...} requires URL to be
                                referenced in an attribute rather than a
                                locally defined OpenLaszlo variable or
                                a compilation error occurs.
      -->
      <attribute name="submit_url" type="string" />

      <!---
      Uploads the currently selected file.

      @param string strURL: (optional) If defined upload the file to this
                            URL, otherwise upload to this.uploadurl

                            Note: required if this.uploadurl is not defined.
      -->
      <method name="upload" args="strURL = false">
      <![CDATA[

        if (strURL === false)
          var strURL = this.uploadurl; // workaround for SWF9/10 compatibility

        this.setAttribute('submit_url', strURL);

        #passthrough  {
           var request:URLRequest = new URLRequest(submit_url);
           file_reference.upload(request);
        }#

      ]]>
      </method>


      <!-- * ABSTRACT handlers: Override to do something useful in instance * -->


      <!--- @keywords abstract -->
      <!---
      ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL

      Called when user selects a file.

      @param flash.events.Event ev: the select event
      -->
      <method name="onSelect" args="ev=null">
        if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onSelect(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
      </method>

      <!--- @keywords abstract -->
      <!---
      ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL

      Called when progress event is captured.

      @param {anything} objDummy: SWF8 requires file_reference object here, does nothing in SWF9/10
      @param number bytesLoaded: the number of bytes of the file uploaded
      @param number bytesTotal: the number of total bytes of the file to be uploaded
      -->
      <method name="onProgress" args="objDummy, bytesLoaded, bytesTotal">
        if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onProgress(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
      </method>

      <!--- @keywords abstract -->
      <!---
      ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL

      Called when a file upload is complete.

      @param flash.events.Event ev: the complete event
      -->
      <method name="onComplete" args="ev=null">
        if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onComplete(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
      </method>

      <!--- @keywords abstract -->
      <!---
      ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL

      Called when the file upload fails.

      @param flash.events.IOErrorEvent/flash.events.securityErrorEvent ev: the Flash Error Event
      -->
      <method name="onError" args="ev=null">
        if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onError(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
      </method>


      <!-- * Internal Private Handlers * -->


      <!--- @keywords private -->
      <!---
      This will pass the progress values to method this.onProgress()

      @param flash.events.ProgressEvent ev: the Flash Progress Event
      -->
      <method name="progressHandler" args="ev=null">
        this.onProgress(false, ev.bytesLoaded, ev.bytesTotal);
      </method>

      <!--- @keywords private -->
      <!---
      This will catch an ioError and call method this.onError()

      @param flash.events.IOErrorEvent ev: the Flash Error Event
      -->
      <method name="ioErrorHandler" args="ev=null">
        if ($debug) Debug.error('as3 (SWF9/10): fileuploadhelper.ioErrorHandler(): ERROR: ioError detected, could not upload file.');
        this.onError(ev);
      </method>

      <!--- @keywords private -->
      <!---
      This will catch a securityError and call method this.onError()

      @param flash.events.securityErrorEvent ev: the Flash Error Event
      -->
      <method name="securityErrorHandler" args="ev=null">
        if ($debug) Debug.error('as3 (SWF9/10): fileuploadhelper.securityErrorHandler(): ERROR: securityError detected. Are you sure you are uploading to same domian as this application is being served from?');
        this.onError(ev);
      </method>

    </class>

  </when>

  <when property="$as2"><!-- SWF8 -->

    <!---
    CLASS: <fileuploadhelper>
    EXTENDS: <node> (lz.node)

    DESCRIPTION:

    This is the ActionScript2(AS2) (SWF8) version of the Flash file
    upload object.

    This allows users to upload files when compiled to a Flash Version that
    uses ActionScript2 such as Flash 8
    -->
    <class name="fileuploadhelper" extends="node">

      <!---
      @param string uploadurl: (optional) default upload url to use if none
                               passed to this.upload()
      -->
      <attribute name="uploadurl" />

      <!--- @keywords private -->
      <!--- @param flash.net.FileReference file_reference: Flash file reference object -->
      <attribute name="file_reference" />

      <!-- *** METHODS *** -->

      <handler name="oninit" args="invoker">
        fr = new flash.net.FileReference();
        this.setAttribute('file_reference', fr);
        fr.addListener(invoker);
      </handler>

      <!-- *** METHODS *** -->

      <!---
      Displays file browsing window and allows the user to select a file (or
      cancel to close the window).
      -->
      <method name="browse">
        this.file_reference.browse();
      </method>

      <!---
      Return name of selected file

      @returns string: the filename of the selected file
      -->
      <method name="getName">
        return this.file_reference.name;
      </method>

      <!---
      Uploads the currently selected file.

      @param string strURL: (optional) If defined upload the file to this
                            URL, otherwise upload to this.uploadurl

                            Note: required if this.uploadurl is not defined.
      -->
      <method name="upload" args="strURL">

        if (strURL == null)
          var strURL = this.uploadurl;

        this.file_reference.upload(strURL);

      </method>


      <!-- * ABSTRACT HANDLERS * -->


      <!--- @keywords abstract -->
      <!---
      ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL

      Called when user selects a file.

      @param flash.events.Event ev: the select event
      -->
      <method name="onSelect" args="ev=null">
        if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onSelect(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
      </method>

      <!--- @keywords abstract -->
      <!---
      ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL

      Called when progress event is captured.

      @param flash.net.fileReference fr: file_reference object here
      @param number bytesLoaded: the number of bytes of the file uploaded
      @param number bytesTotal: the number of total bytes of the file to be uploaded
      -->
      <method name="onProgress" args="fr, bytesLoaded, bytesTotal">
        if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onProgress(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
      </method>

      <!--- @keywords abstract -->
      <!---
      ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL

      Called when a file upload is complete.

      @param flash.events.Event fr: the file_reference object
      -->
      <method name="onComplete" args="fr=null">
        if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onComplete(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
      </method>

      <!--- @keywords abstract -->
      <!---
      ABSTRACT METHOD: OVERRIDE IN YOUR APPLICATION TO DO SOMETHING USEFUL

      Called when the file upload fails.

      @param flash.events.Event fr: the file_reference object
      -->
      <method name="onError" args="fr=null">
        if ($debug) Debug.info('as3 (SWF9/10): fileuploadhelper.onError(): WARNING: This is an abstract method that should be overridden in your application to do something useful...');
      </method>

    </class>

  </when>

</switch>

</library>

Note: This works similar to an HTML form where you post the file upload to a receiving script on the backend (could be in PHP, ASP, etc.) which would process the file and store it somewhere, there are many tutorials on the web on how to do that so I have not included it. As for drag and drop and preview you would have to write a fairly complicated application in OpenLaszlo yourself to do this, I suggest you view the tutorials and OpenLaszlo documentation to learn how to do that.