2

i found a few scripts online and combined them to this. I want to download files from the web to my local harddrive. Any idea what i'm doing wrong?

var fs:FileStream;
var stream:URLStream;
var _output:Boolean = false;

init();
startDownload('http://www.teachenglishinasia.net/files/u2/purple_lotus_flower.jpg');

function init() { 
    stream = new URLStream();
    stream.addEventListener(ProgressEvent.PROGRESS, _dlProgressHandler); 
    stream.addEventListener(Event.COMPLETE, _dlCompleteHandler);
    stream.addEventListener(Event.OPEN, _dlStartHandler);
    fs = new FileStream();
    fs.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, _writeProgressHandler)
}

function startDownload(url:String):void {
     //fs.openAsync(lfile, FileMode.APPEND);
     _output = false;
     stream.load(new URLRequest(url));
}

function downloadComplete():void {
     var fileData:ByteArray = new ByteArray();
     stream.readBytes(fileData,0,stream.bytesAvailable);
     fs.writeBytes(fileData,0,fileData.length);
     fs.close(); 
}

function writeToDisk():void {
     _output = false;
     var fileData:ByteArray = new ByteArray();
     stream.readBytes(fileData,0,stream.bytesAvailable);
     fs.writeBytes(fileData,0,fileData.length);
}

function _dlProgressHandler(evt:ProgressEvent):void {
     if(_output){
         writeToDisk();   
     }
}

function _dlCompleteHandler(evt:Event):void { 
    downloadComplete();
} 

function _dlStartHandler(evt:Event):void {
     _output = true; 
}

function _writeProgressHandler(evt:OutputProgressEvent):void{
     _output = true;
}

Flash keeps telling me: Error: Error #2029: This URLStream object does not have a stream opened. However the connection to the webpage goes out.

Any ideas? Thank you for your help!

matt
  • 42,713
  • 103
  • 264
  • 397

2 Answers2

5

I modified your code and here is a working Downloader class. (@SébastienNussbaumer improved this answer and @TobiasKienzler reviewed changes: thanks a lot guys!)

Simple to use:

var downLoader:Downloader = new Downloader();
downLoader.addEventListener(DownloadEvent.DOWNLOAD_COMPLETE, function(event:DownloadEvent):void{
    trace("Download complete: ");
    trace("\t"+event.url);
    trace("->\t"+event.file.url);
});
var file:File = File.applicationStorageDirectory.resolvePath("downloaded.mp3");
downLoader.download("http://dl.dropbox.com/u/18041784/Music/Lana%20Del%20Rey%20-%20Born%20To%20die%20%28Gemini%20Remix%29.mp3", file);

Output when download complete:

Download complete: 
    http://dl.dropbox.com/u/18041784/Music/Lana%20Del%20Rey%20-%20Born%20To%20die%20%28Gemini%20Remix%29.mp3
->  app-storage:/downloaded.mp3

Enjoy:-)

package com.tatstyappz.net
{
    import flash.events.DataEvent;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.OutputProgressEvent;
    import flash.events.ProgressEvent;
    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 Downloader extends EventDispatcher
    {
        [Event(name="DownloadComplete", type="com.tatstyappz.net.DownloadEvent")]

        private var file:File;
        private var fileStream:FileStream;
        private var url:String;
        private var urlStream:URLStream;

        private var waitingForDataToWrite:Boolean = false;

        public function Downloader()
        {
            urlStream = new URLStream();

            urlStream.addEventListener(Event.OPEN, onOpenEvent);
            urlStream.addEventListener(ProgressEvent.PROGRESS, onProgressEvent); 
            urlStream.addEventListener(Event.COMPLETE, onCompleteEvent);

            fileStream = new FileStream();
            fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeProgressHandler)

        }

        public function download(formUrl:String, toFile:File):void {
            this.url = formUrl;
            this.file = toFile;
            fileStream.openAsync(file, FileMode.WRITE);
            urlStream.load(new URLRequest(url));
        }

        private function onOpenEvent(event:Event):void {
            waitingForDataToWrite = true;

            dispatchEvent(event.clone());
        }

        private function onProgressEvent(event:ProgressEvent):void {
            if(waitingForDataToWrite){
                writeToDisk();
                dispatchEvent(event.clone());
            }
        }

        private function writeToDisk():void {
            var fileData:ByteArray = new ByteArray();
            urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
            fileStream.writeBytes(fileData,0,fileData.length);
            waitingForDataToWrite = false;

            dispatchEvent(new DataEvent(DataEvent.DATA));
        }

        private function writeProgressHandler(evt:OutputProgressEvent):void{
            waitingForDataToWrite = true;
        }

        private function onCompleteEvent(event:Event):void {
            if(urlStream.bytesAvailable>0)
                writeToDisk();
            fileStream.close();

            fileStream.removeEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeProgressHandler);

            dispatchEvent(event.clone());
            // dispatch additional DownloadEvent
            dispatchEvent(new DownloadEvent(DownloadEvent.DOWNLOAD_COMPLETE, url, file));
        }

    }
}

And the event class:

package com.tatstyappz.net
{
    import flash.events.Event;
    import flash.filesystem.File;

    public class DownloadEvent extends Event
    {
        public static const DOWNLOAD_COMPLETE:String = "DownloadComplete";

        public var url:String;
        public var file:File;

        public function DownloadEvent(type:String, url:String, file:File)
        {
            super(type, true);
            this.url = url;
            this.file = file;
        }

        override public function toString():String{
            return super.toString() + ": "+ url + " -> "+file.url;
        }
    }
}
Pascal
  • 15,257
  • 2
  • 52
  • 65
  • @SébastienNussbaumer You should have left a comment to let Pascal know about this – Tobias Kienzler Aug 06 '13 at 07:40
  • Hi, someone just tried to modify the answer about "corrected bug : waitingForDataToWrite was always false, the progress event would not be dispatched and the downloaded file would go completely in memory" But it was probably rejected (not by me). Feel free to send me updated code so I can modify myself (and credit the author) pascal.dalfarra[at]gmail.com – Pascal Aug 06 '13 at 08:25
  • You mean [this one](http://stackoverflow.com/review/suggested-edits/2662320)? It got accepted, though to me it sounded severe enough to prefer discussion with you instead of directly approving it. If it's a follow-up, unfortunately rejected suggestions are near-impossible to find except in the review queue. Here's another one also by @Sébastien which got rejected before: http://stackoverflow.com/review/suggested-edits/2662084 – Tobias Kienzler Aug 06 '13 at 08:28
  • @Tobias : gotcha, I hesitated ... I'll go with the comments in the future. – Sébastien Nussbaumer Aug 06 '13 at 08:39
  • @Pascal : the important modification was accepted. (with the two following changes : in Downloader.download in changed fileStream.open to fileStream.openAsync, and in Downloader.onOpenEvent I changed waitingForDataToWrite from false to true). There was an other minor edit which was rejected (don't know why, maybe because I did two edits), I just removed "import.flash.media.Sound" in DownloadEvent which was unncessary, so really not important at all ... – Sébastien Nussbaumer Aug 06 '13 at 08:39
  • @SébastienNussbaumer and @ TobiasKienzler Thanks a lot for your work on this. So, now the code is working fine. KR, Pascal – Pascal Aug 06 '13 at 11:49
  • @Pascal You shouldn't thank me, I actually voted to reject that edit since I thought "turning a false into a true shouldn't happen without discussion"... – Tobias Kienzler Aug 06 '13 at 13:36
0

This is a long shot, since I've never worked with FileStream (and since the error message you pasted says 'this URLStream object etc'). But, It seems you FileStream object (fs) is not open and you are trying to 1) write to it and then 2) close it. My understanding is that any of those operations should throw an error if the file is not open. So, maybe it's worth cheking that. Other than that, can you paste a stack trace of the error, so it's more clear where it originates? (Tip: if you are compiling with the Flash IDE, check permit debugging in the actionscript settings; this will give you more verbose error messages and line numbers; this is of great help when debugging / troubleshooting).

Juan Pablo Califano
  • 12,213
  • 5
  • 29
  • 42