0

I'm making an AIR app in which the user drags and drops image files onto the stage, the app then uploads those dropped images to the site imgur.com, and then returns with links to the images (in XML format).

I am having two issues:

  1. the program works successfully with a very small file, however anything larger (1mb or more), I get an IOStream error 2023. Imgur supports uploads of up to 10mb so I know it must be something on my end.

  2. I would like to be able to drop multiple image files at once into the program, and have it upload all of them (either synchronously or asynchronously, it does not matter). Right now the program gives errors when I attempt to do this (something along the lines of the byteArray having to be greater than 0).

Below is the code in question which is giving me issues. (thank you for your help in advanced)

private function doDragDrop(e:NativeDragEvent):void
{           
    trace("doDragDrop() called.");
    var dropFiles:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
    for each (var file:File in dropFiles)
    {
        switch (file.extension.toLowerCase())
        {
            case "jpg" :
            case "jpeg" :
            case "gif" :
            case "png" :
            case "apng" :
            case "tiff" :
            case "bmp" :
            case "pdf" :
            case "xcf" :
            trace("file Extension Check = passed");
            addImage(file.nativePath);
                break;

            //error handling for non-supported filetypes
            default :
                trace("ERROR: Unsupported File Type Detected!");
        }
    }
}

private function addImage(nativePath:String):void
{
    trace("addImage() called.");
    trace("NativePath is: " + nativePath);
    //var file:File = new File(nativePath);
    var file:File = File.desktopDirectory.resolvePath(nativePath);
    var ba:ByteArray = new ByteArray();
    var stream:FileStream = new FileStream();
    stream.open(file, FileMode.READ);
    stream.readBytes(ba);
    stream.close();         
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, fileLoaded);
    loader.loadBytes(ba);
}

private function fileLoaded(e:Event):void
{
    trace("fileLoaded() called.");
    var bitmap:Bitmap = Bitmap(e.target.content);
    var bitmapData:BitmapData = bitmap.bitmapData;
    var png:ByteArray = PNGEncoder.encode(bitmapData);

    urlLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
    urlLoader.addEventListener(Event.COMPLETE, onCookieSent);
    urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
    urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);

    var vars:String = "?key=" + API_KEY + "&name=name&title=title";
    var request:URLRequest = new URLRequest(UPLOAD_URL + vars);
    request.contentType = "application/octet-stream";
    request.method = URLRequestMethod.POST;
    request.data = png;
    urlLoader.load(request);
}

private function onCookieSent(e:Event):void
{
    trace("onCookieSent() called.");
    var res:XML = new XML(unescape(urlLoader.data));
    var resultsList:XMLList = res.links;
    trace(resultsList);
}

private function onIOError(e:IOErrorEvent):void 
{
    trace("ioErrorHandler: " + e);
    TweenLite.to(tv_mc, 2, {alpha:0.5, scaleX:1.0, scaleY:1.0, ease:Elastic.easeOut});
    // Handle error
}
private function onSecurityError(e:SecurityErrorEvent):void 
{
    trace("securityErrorHandler: " + e);
    TweenLite.to(tv_mc, 2, {alpha:0.5, scaleX:1.0, scaleY:1.0, ease:Elastic.easeOut});
    // handle error
}

//When the dragged object leaves the drop point, do this
private function doDragExit(e:NativeDragEvent):void
{
    trace("doDragExit() called.");
    TweenLite.to(tv_mc, 2, {alpha:0.5, scaleX:1.0, scaleY:1.0, ease:Elastic.easeOut});
}
Dominique
  • 16,450
  • 15
  • 56
  • 112
tdc
  • 5,174
  • 12
  • 53
  • 102

1 Answers1

1

after doing this:

var ba:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
stream.readBytes(ba);
stream.close(); 

you already have a ByteArray of the file/image. can't you just send this one...

private function addImage(nativePath:String):void
{
    trace("addImage() called.");
    trace("NativePath is: " + nativePath);
    //var file:File = new File(nativePath);
    var file:File = File.desktopDirectory.resolvePath(nativePath);
    var ba:ByteArray = new ByteArray();
    var stream:FileStream = new FileStream();
    stream.open(file, FileMode.READ);
    stream.readBytes(ba);
    stream.close();         

    urlLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
    urlLoader.addEventListener(Event.COMPLETE, onCookieSent);
    urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
    urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);

    var vars:String = "?key=" + API_KEY + "&name=name&title=title";
    var request:URLRequest = new URLRequest(UPLOAD_URL + vars);
    request.contentType = "application/octet-stream";
    request.method = URLRequestMethod.POST;
    request.data = ba;
    urlLoader.load(request);
}
Philipp Kyeck
  • 18,402
  • 15
  • 86
  • 123
  • Hi pkyeck, seems like you're always helping me out on here, I appreciate it :) The code you suggested works beautifully. I had pulled a lot of that code from a previous project and had forgotten to remove some unneeded bits so thank you! The app now uploads both small and big images fine. I just have 2 more things I want to tackle: 1) being able to track the % uploaded progress (it seems URLLoader only dispatches a 0 or a 100% for progressEvent?) and 2)Allow multiple files to be dropped in at once, and have them all uploaded. Any suggestions for tackling those? Thanks again for the help! – tdc Jan 26 '12 at 17:41
  • glad i could help. (don't forget to accept the answer then ...). for the two remaining Qs: 1) normally you should get more than just the 0 and 100%. is it so fast that there is no time for more? 2) build a queue so that when you drag'n'drop multiple files you upload them one by one. – Philipp Kyeck Jan 26 '12 at 22:59
  • No, I don't think it is so fast, as I'll use a 6mb image and the upload will take a good 30 seconds. I added a progressEvent.PROGRESS event to the urlLoader, and in the handler trace out (e.bytesLoaded/e.bytesTotal)*100. It only ever traces "0%" and "100%". :( 2)Any recommendation on building a queue? Should I just check to see if the file ends with a proper extension, store the file path in an array and then loop through the array when doing image loading/uploading? – tdc Jan 27 '12 at 03:05
  • 1) http://stackoverflow.com/questions/1512197/image-upload-progress-using-urlloader-as3 seems like progress monitoring while uploading files is not supported. 2) yes, add every file to an array and start uploading the first. after this is finished, remove it from the array and start the first again (former second index in array) - until there are none left in the array. – Philipp Kyeck Jan 27 '12 at 08:29