Skip to content


Downloading Files with Flex 3

So I was reviewing the documentation over at Adobe for downloading files with Flex – I tweaked the code a little so I can specify the file to download inside my .mxml file rather than the .as file -this demo will download the source files for my papervision with multiple sides demo.

Here is my modified class file, I simply made the DOWNLOAD variable to be a public variable and added this as a parameter to the init function:

package com.example.programmingas3.fileio {
    import flash.events.*;
    import flash.net.FileReference;
    import flash.net.URLRequest;

    import mx.controls.Button;
    import mx.controls.ProgressBar;
    import mx.core.UIComponent;

    public class FileDownload extends UIComponent {

        public var DOWNLOAD_URL:String;
        private var fr:FileReference;
        // Define reference to the download ProgressBar component.
        private var pb:ProgressBar;
        // Define reference to the "Cancel" button which will immediately stop the download in progress.
        private var btn:Button;

        public function FileDownload() {

        }

        /**
         * Set references to the components, and add listeners for the OPEN,
         * PROGRESS, and COMPLETE events.
         */
        public function init(pb:ProgressBar, btn:Button, dURL:String):void {
            // Set up the references to the progress bar and cancel button, which are passed from the calling script.
            this.pb = pb;
            this.btn = btn;

            DOWNLOAD_URL = dURL;

            fr = new FileReference();
            fr.addEventListener(Event.OPEN, openHandler);
            fr.addEventListener(ProgressEvent.PROGRESS, progressHandler);
            fr.addEventListener(Event.COMPLETE, completeHandler);
        }

        /**
         * Immediately cancel the download in progress and disable the cancel button.
         */
        public function cancelDownload():void {
            fr.cancel();
            pb.label = "DOWNLOAD CANCELLED";
            btn.enabled = false;
        }

        /**
         * Begin downloading the file specified in the DOWNLOAD_URL constant.
         */
        public function startDownload():void {
            var request:URLRequest = new URLRequest();
            request.url = DOWNLOAD_URL;
            fr.download(request);
        }

        /**
         * When the OPEN event has dispatched, change the progress bar's label
         * and enable the "Cancel" button, which allows the user to abort the
         * download operation.
         */
        private function openHandler(event:Event):void {
            pb.label = "DOWNLOADING %3%%";
            btn.enabled = true;
        }

        /**
         * While the file is downloading, update the progress bar's status and label.
         */
        private function progressHandler(event:ProgressEvent):void {
            pb.setProgress(event.bytesLoaded, event.bytesTotal);
        }

        /**
         * Once the download has completed, change the progress bar's label and
         * disable the "Cancel" button since the download is already completed.
         */
        private function completeHandler(event:Event):void {
            pb.label = "DOWNLOAD COMPLETE";
            pb.setProgress(0, 100);
            btn.enabled = false;
        }
    }
}

Here is my mxml file:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:example="com.example.programmingas3.fileio.*" xmlns="*" horizontalAlign="center">
<example:FileDownload id="fileDownload" creationComplete="fileDownload.init(downloadProgress, cancelDownload,’http://manewc.com/projects/flash/PapervisionCubeSides/PapervisionCubeSides.zip’);" />
<mx:HBox>
<mx:Panel title="Download File" paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
<mx:ProgressBar id="downloadProgress" label="" mode="manual" />
<mx:ControlBar horizontalAlign="right">
<mx:Button id="startDownload" label="Download…" click="fileDownload.startDownload();" />
<mx:Button id="cancelDownload" label="Cancel" click="fileDownload.cancelDownload();" enabled="false" />
</mx:ControlBar>
</mx:Panel>
</mx:HBox>
</mx:Application>

Posted in Actionscript 3, Flex Web Development.


26 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Noah Smith says

    you sure do a lot of good work with out any comments. i think it is appropriate for me to let you know that i read every one of your posts. good stuff.

  2. Noah Smith says

    and by “with out any comments” i dont mean code comments…. i mean comments by your readers. perhaps i should have stuck with “replies”

  3. Yaz says

    I agree Noah, considering the vast amount of information on Morgan site, its hard to believe that there isn’t more interaction with the readers.
    I also read every post, and Morgan is also kind enough to email me when I ask him questions.

    Thanks for all the great code Morgan.

    I just started to pick up flex, and I have to admit, it was because of your recommendation!

    also I figured out the Name space issue with RSS feeds, let me know if you want to have a look at the class.

  4. admin says

    Hey Yaz and Noah, I appreciate the comments – even though I don’t mind posting my files for little projects that I have done or modified – it has really been just a learning experience.

    Thanks again, Morgan

  5. admin says

    Oh, and Yaz, glad to hear that you picked up Flex! As much as I love to work in Flash CS3, I feel that Flex opens up a new dimension to Actionscript, you will get a lot out of it! (plus I feel that Flash is slowly migrating back to it’s roots as a “designer” piece of software) – Also would love to see your updated Class on the name space issue.

    Morgan

  6. corey says

    Thanks Morgan. I have a quick question: I want to enable multiple file downloads with one click. Like, you select a few different pdfs from a list of checkboxes which puts them in an array and then when you click “Download” it cues the files and downloads them all. Is this possible?
    thanks for the great code!

  7. admin says

    Hey Corey, This sounds like a nice little project – I have been out for a while trying to think of new stuff and this one sounds interesting.

    Thanks, I’ll keep you posted.

    Morgan

  8. Jerome says

    Hi,

    Did someone succeed for the multiple upload ? I just can’t find a solution… :(

  9. Jerome says

    wooops ! sorry, means “multiple download” not “multiple upload”

  10. admin says

    Hi again, I just wanted to let you know that I created a little demo that will zip up files in an array and allow the user to download the newly created zip. You can find it here:

    http://manewc.com/2008/12/22/downloading-multiple-files-with-flex-3/

    PHP required.

    Thanks Morgan

  11. Daniel says

    Any thoughts on how I can have the app download files that are in a folder below the web root (below public_html) for security purposes so that the file is not directly accessible through the browser?

    Thanks!

  12. admin says

    I have a feeling that this would not be possible and you would have to secure a folder the file is located in as well as process some authentication before the user can download the file. Although, I could be incorrect as it may be dependent on your server setup.

  13. Daniel says

    Thx for the reply…that’s what I feared.
    If I password protect the directory, then Flex is not able to access the files either, and if it is below root, I can’t get to it from Flex either.

    I have a PHP script that is able to access the files below root and force a download prompt, but when I call the script via Flex, it doesn’t seem to work…not sure why, seems like Flex is blocking the PHP script from properly executing the force download.

  14. admin says

    Hmm… out of curiousity are you using something like AMFPHP to process your php methods? When I get more time I’m am interested in setting up something like this to try and get it to work. Also, are you using PHP5?

  15. Daniel says

    No, I haven’t looked into implementing AMFPHP yet (eventhough I really should)…the PHP script receives a file ID (either as a POST or GET) and creates the correct headers for a force download of that file which is below the webroot…and it works like a charm if I don’t use Flex, but with Flex it processes, but no download is initiated.

    As for PHP5, the clients server isnt on 5 yet and their other apps would get affected if I moved them over, so I’m stuck dealing with 4 for now :(

  16. Daniel says

    Well, just thought of something and wanted to get your feedback on it…kind of a convoluted possible solution, but ohwell:

    When the user hits a Download button in Flex, Flex calls a PHP script with the id of the file. The PHP script then takes a copy of the file to be downloaded and places it temporarily into an accessible temp folder. It returns a success msg to Flex when it does this and Flex then uses URLRequest & FileReference to download the file. Once download it complete, Flex calls another small PHP script that removes the temporary file and clears the directory, ready for the next file download.

    My worries:
    a) there MUST be an easier way
    b) this could make execution time for the script quite long where the user doesn’t know what is going on especially if its even a remotely larger file
    c) how do you tell if the user actually downloaded the file yet to send the request to the PHP script to remove the file now? Or do you just make it time based where after 1 minute it clears the file?

    Just a thought (brainstorming), so I might be completely off here.D

  17. admin says

    I share your concerns, they are very valid. There certainly is a lot of communication between Flex and PHP, but I do assume that it is possible. Is it possible to create the same purchasing process as e-commerce for digital downloads? ie: provide the user via email with a link to download the file for a specified amount of time.

  18. Daniel says

    That’s definitely a possibility, but the problem is that I need to have it where the file can be downloaded directly from the application.

    I guess a last (and my least favorite) alternative would be to open the PHP download script in a new window above the Flex app so that the download works and use javascript to close to browser upon completion?

  19. admin says

    is this something where you need to view the progress event within the flex app? or is it something where you simply click the button in the flex app and the file just downloads? if it is the latter then there is a good chance that amfphp is your solution.

  20. Daniel says

    its the latter in this case where you simply click, get the download dialog and download.

    amfphp would overcome this issue then?
    ill try it and let you know…

  21. Daniel says

    UPDATE:

    Well, I got it to work with no AMFPHP (I just haven’t had time to go that route)…I used a modified force download PHP script that I called with navigateToURL…the force download script loads, pushes the download dialog to the user and closes the newly opened window…all very quickly.

    So now I can place files below the web accessible level without any problems.

  22. admin says

    Sweet! Glad to hear that you got it working.. sounds like it is fast which is cool.

    Is there a demo with write up somewhere?

    Thanks, Morgan

  23. Daniel says

    Nothing available right now, but I’ll put a demo up and include the source files….I’ll post the link on here.

    Thanks for your help throughout this process….

    ps – bad news: Safari actually opens the file rather than forcing a download….maybe its a header thing in the PHP file…but works fine in IE and FireFox.

  24. admin says

    Thanks Daniel, I wonder how Safari v4 beta will treat the download. Anyways, looking forward to the demo.

  25. Kasper says

    Heya,

    I’d just like to ask since I am pretty new to all this Flex stuff how and where and what do I name and place my Class file?

    Regards

  26. tahir says

    very nice work done, very good



Some HTML is OK

or, reply to this post via trackback.