views:

4790

answers:

11

How do I download a file from the internet in a Flex based AIR application.

I tried using a file with url set to the address, but I got a file does not exist error when I tried to save it. And it is really hard to google for help on this issue.

A: 

Check out the flash.net.URLRequest class which will help you to download the file.

Swaroop C H
+4  A: 

You want to choose from 2 api combos to accomplish this.

Version 1 is URLLoader and FileStream

Using this combination of class, you would load the file from your server in to air via the URLLoader object. This will download the file in to memory and then notify you when the download is complete. Make sure you initiate the download with a dataFormat of URLLoaderDataFormat.BINARY. You would then initiate a Filestream object and write it out to the disk using writeBytes().

Version 2 is URLStream and FileStream

URLStream is very similar to URLLoader, but instead of waiting for the file to completely download before using the result, data is made available to you during the download. This method works well for large files because you don't have to wait for the full download to start saving it to disk, and you also save on memory since once the player hands it off to you it can release the memory related to that data. YOu would use filestream in exactly the same way, you would just end up doing a writeBytes() on each chunk of the file as it streams in.

seanalltogether
+3  A: 

To build on seanalltogether's second idea, here is a function that should download a file from the internet, and save it to disk (in the specified file name on the desktop):

downloadFile: function (url, fileName) {
 var urlStream = new air.URLStream();
 var request = new air.URLRequest(url);
 var fileStream = new air.FileStream();
 // write 50k from the urlstream to the filestream, unless
 // the writeAll flag is true, when you write everything in the buffer
 function writeFile(writeAll) {
  if (urlStream.bytesAvailable > 51200 || writeAll) {
   alert("got some");
   var dataBuffer = new air.ByteArray();
   urlStream.readBytes(dataBuffer, 0, urlStream.bytesAvailable);
   fileStream.writeBytes(dataBuffer, 0, dataBuffer.length);
  }
  // do clean up:
  if (writeAll) {
   alert("done");
   fileStream.close();
   urlStream.close();
   // set up the next download
   setTimeout(this.downloadNextFile.bind(this), 0);
  }
 }

 urlStream.addEventListener(air.Event.COMPLETE, writeFile.bind(this, true));
 urlStream.addEventListener(air.ProgressEvent.PROGRESS, writeFile.bind(this, false));

 var file = air.File.desktopDirectory.resolvePath(fileName);
 fileStream.openAsync(file, air.FileMode.WRITE);

 urlStream.load(request);

}

Note: This solution uses Prototype, and AIRAliases.js.

pkaeding
A: 

Good evening my friend. My name is Vieira

I'm from Brazil, Belo Horizonte, Minas Gerais state. Contact E-mail: [email protected]

I am starting on FLEX AIR need to download an exe file from a Web server automatically without interference of the User and save it to disk and run it run it through the Flex AIR.

I took his role on the web, but do not know how to implement it in my application.

It is possible you pass me an example of using this function in a small application FLEX AIR? Deesde already thank you for your attention. thank you very much.

Vieira

Vieira
If you have a new question, please click the 'Ask Question' button at the top-right of the page, rather than tacking on your question as an answer to this question.
pkaeding
A: 

Hi, When trying your code, I have a js alaert (got some) then (done) then this error message :

TypeError: Undefined value

What is the problem ?

Never mind, I just commented this line : setTimeout(this.downloadNextFile.bind(this), 0);

I don't understand what it does, I think that setTimeout does not work in AIR due to security mechanisms ...

How can I make the user choose the destination directory ?

Sami_c
+1  A: 

I used seanalltogether's answer, and wrote this class to handle file downloading.

It is pretty simple. create a var downloader = new FileDownloader("url", "Local/Path"); and call downloader.load() to start downloading.

It also supports setting a function to be called when done, and at points while downloading. Passing the onProgress function the number of bytes that have been downloaded. ( I could not figure out how to get a fraction, since I could not figure out how to query the size of the file before it was downloaded)

package com.alex{
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.URLRequest;
import flash.net.URLStream;
import flash.utils.ByteArray;

public class FileDownloader
{

 // Class to download files from the internet

 // Function called every time data arrives
 //   called with an argument of how much has been downloaded
 public var onProgress :Function = function(t:uint):void{};
 public var onComplete :Function = function():void{};
 public var remotePath :String = "";
 public var localFile :File = null; 

 private var stream :URLStream;
 private var fileAccess :FileStream;

 public function FileDownloader( remotePath :String = "" , localFile :File = null ) {

  this.remotePath = remotePath;
  this.localFile = localFile;
 }

 public function load() :void {
  if( !stream || !stream.connected ) {
   stream = new URLStream();
   fileAccess = new FileStream();

   var requester :URLRequest = new URLRequest( remotePath );
   var currentPosition :uint = 0;
   var downloadCompleteFlag :Boolean = false;

   // Function to call oncomplete, once the download finishes and
   //   all data has been written to disc    
   fileAccess.addEventListener( "outputProgress", function ( result ) :void {
    if( result.bytesPending == 0 && downloadCompleteFlag ) {

     stream.close();
     fileAccess.close();
     onComplete();
    }
   });

   fileAccess.openAsync( localFile, FileMode.WRITE );

   stream.addEventListener( "progress" , function () :void {

    var bytes :ByteArray = new ByteArray();
    var thisStart :uint = currentPosition;
    currentPosition += stream.bytesAvailable;
    // ^^  Makes sure that asyncronicity does not break anything

    stream.readBytes( bytes, thisStart );
    fileAccess.writeBytes( bytes, thisStart );

    onProgress( currentPosition );      
   });

   stream.addEventListener( "complete", function () :void {
    downloadCompleteFlag = true;
   });

   stream.load( requester );

  } else {
   // Do something unspeakable
  }
 }
}}
AlexH
A: 

hey man, thank you for this one, you save my day!! I would only add instance definition of value "result" to OutputProgressEvent THANK YOU

nemo
A: 

may i know whether there is any dependency for Flash player with flex SDK to run a flex project (back end -java)

rose
If you have a new question, please click the 'Ask Question' button at the top-right of the page, rather than tacking on your question as an answer to this question.
pkaeding
A: 

Hello,

I am getting an error "Value undefined does not allow function call" at urlStream.addEventListener(air.Event.COMPLETE, writeFile.bind(this, true));

I am using the download method in simple adobe air application.

Please help

A: 

Please need help: and getting URLSTREAM Object does not have a stream opened at stream.bytesAvailable Line Here is my code : HelloWorld.html

<head>
    <title>Dev Web Applications</title>
    <script language="javascript" type="text/javascript" src="AIRAliases.js"></script>
    <script language="javascript">
        var stream; 
        var fileAccess; 
        var Exposed = {};
        Exposed.trace = function(url) {     
            air.trace("Url is: " + url);    
            air.trace(url.substr(0,4));
            var urlReq;
            if(url.substr(0,4)=="http"){
                urlReq = new air.URLRequest(url);                       
                air.navigateToURL(urlReq);  
            }
            else{
                urlReq =(url);                      
                url="\\\\Dev\\c$\\Playing\\ReportViewer\\Financial\\TestingReport.xls"
                air.trace(url);                 
                var requester = new air.URLRequest(url);    

                if( !stream || !stream.connected ) { 
                    stream = new air.URLStream(); 
                    fileAccess = new air.FileStream(); 
                    air.trace("Stream is open");
                    function writeFile(flag)
                    {

                        air.trace("downloadCompleteFlag: "+flag);
                        if (stream.bytesAvailable > 51200 || flag ) { 
                                    air.trace("got some");
                                    var dataBuffer = new air.ByteArray(); 
                                    stream.readBytes(dataBuffer, 0, stream.bytesAvailable); 
                                    fileAccess.writeBytes(dataBuffer, 0, dataBuffer.length); 
                        } 
                            // do clean up: 
                        if (flag) { 
                                    air.trace("done"); 
                                    fileAccess.close(); 
                                    stream.close(); 
                                    // set up the next download 
                                    //setTimeout(this.downloadNextFile.bind(this), 0); 
                        } 
                    }


                    stream.addEventListener(air.Event.COMPLETE, writeFile(true));
                    var localFile = air.File.desktopDirectory.resolvePath("xyz.xls"); 
                    fileAccess.openAsync( localFile, FileMode.WRITE );                      
                    stream.addEventListener(air.ProgressEvent.PROGRESS,writeFile(false));
                    stream.load(requester);
                }
                else{
                air.trace("Do Nothing");
                }

            }

        }
        function engageBridge(){

            document.getElementById('remoteContent').contentWindow.parentSandboxBridge = Exposed;   
        }
        function init() {
            window.nativeWindow.addEventListener(air.Event.CLOSING, onClosingEvent);
            window.nativeWindow.maximize();
        }
        function onClosingEvent(event) {
            if (!confirm("Exit Dierbergs Web Applications?  Any unsaved changes will be lost."))
                event.preventDefault();
        }

    </script>
</head>
<body onload="init()">
    <!-- Load into a frame to preserve the javascript in this file. -->
    <frameset rows="100%">
        <frame id="remoteContent" src="http://Dev/zkintranet/index.zul"  ondominitialize="engageBridge()"/> 
    </frameset>


</body>
A: 

Hii,

If I've downloaded a video, for example, can I protect it to copy or does it make availible just for a time?

How can I do it?

Thanks

Philippe
If you have a new question, please click the 'Ask Question' button at the top-right of the page, rather than tacking on your question as an answer to this question.
pkaeding