R – URLLoader fails randomly without throwing an error or dispatching any events

actionscript-3airapache-flex

In Adobe AIR 1.5, I'm using URLLoader to upload a video in 1 MB chunks. It uploads 1 MB, waits for the Event.COMPLETE event, and then uploads the next chunk. The server-side code knows how to construct the video from these chunks.

Usually, it works fine. However, sometimes it just stops without throwing any errors or dispatching any events. This is an example of what is shown in a log that I create:

Uploading chunk of size: 1000000
HTTP_RESPONSE_STATUS dispatched: 200
HTTP_STATUS dispatched: 200
Completed chunk 1 of 108

Uploading chunk of size: 1000000
HTTP_RESPONSE_STATUS ...

etc…

Most of the time, it completes all of the chunks fine. However, sometimes, it just fails in the middle:

Completed chunk 2 of 108
Uploading chunk of size: 1000000

… and nothing else, and no network activity.

Through debugging, I can tell that it does successfully call urlLoader.load(). When it fails, it just seems to stall, calling load(), and then calling the UIComponent's callLaterDispatcher() and then nothing.

Does anyone have any idea why this could be happening? I'm setting up my URLLoader like this:

urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, chunkComplete);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, responseStatusHandler);
urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, statusHandler);
urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);

And I'm re-using it for each chunk. No events get called when it doesn't succeed, and urlLoader.load() doesn't throw any exceptions. When it succeeds, HTTP_RESPONSE_STATUS, HTTP_STATUS, and PROGRESS events are dispatched.

Thanks!

Edit: One thing that might be helpful is that, we have the same upload functionality implemented in .NET. In .NET, the request.GetResponse() method sometimes throws an exception, complaining that the connection was closed unexpectedly. We catch the exception if this happens, and try that chunk again, until it succeeds. I'm looking to implement something similar here, but there are no exceptions being thrown or error events being dispatched.

More detailed code example below. The URLLoader is setup as described above. The readAgain variable just makes it skip reading a new set of bytes in the file stream (ie: it tries to send the old one again) … however, it never catches any exceptions, because none are ever thrown.

private function uploadSegment():void
{
    .... prepare byte array, setup url ...

    // Create a URL request
    var urlRequest:URLRequest = new URLRequest();
    urlRequest.url = _url + "?" + paramStr; 
    urlRequest.method = URLRequestMethod.POST;
    urlRequest.data = byteArray;
    urlRequest.useCache = false;
    urlRequest.requestHeaders.push(new URLRequestHeader('Cache-Control', 'no-cache'));

    try
    {
        urlLoader.load(urlRequest);
    }
    catch (e:Error)
    {
        Logger.error("Failed to upload chunk. Caught exception. Trying again.");
        readAgain = true;
        uploadSegment();
        return;
    }

    readAgain = false;
}

Best Answer

Have you tried signing up for 'Event.OPEN' to see if the connection is opening correctly? If you're doing this per chunk - perhaps that event or lack thereof would help?

[Edit]

Can you also try setting useCache to false on your URLRequest?

[Edit]

I assume you're urlLoader is globally referenced... If not, while you're waiting for async behavior, something evil like GC might hurt you ... But - skipping that, if you call 'bytesTotal' while you're waiting for something to happen - does it always return zero?

[More]

Also - check the URL in the cases where NOTHING happens - because online I've found some mention that if the server is unreachable there are no events fired (though there is some argument around that)...

Related Topic