Uploading to S3 with a FileReference from Flex 3 on OS X
After working on a fairly simple upload from Flex to Amazon S3, a co-worker claimed it was "done". Ok. Then I tried uploading from from my mac. No dice. So this simple upload went from being "done" to "a significant OS X pain." Here are some of the things that helped.
After much googling, Wiresharking, and general debuggation, a co-worker found this Amazon S3 doc, which notes:
Some versions of the Adobe Flash Player do not properly handle HTTP responses that have an empty body. To configure POST to return a response that does not have an empty body, set success_action_status to 201. When set, Amazon S3 returns an XML document with a 201 status code. For information on the content of the XML document, see ???. For information on form fields, see HTML Form Fields.
Interesting. And small; it is a tiny message, almost a footnote, on some Amazon page. I wish Adobe could get their docs together. I particularly like "Some versions" and "???". Anyway, lesson learned, or at least we have something to try.
The S3/Flash interactions need a little massaging
It seems like the OS X Flash runtime (9.0.115.0) requires a non-empty server response from its POST. Amazon S3 conveniently has an additional parameter, success_action_status which can be set to "201" to have S3 respond to the post with a 201 CREATED response code. If you are uploading to Apache or IIS, you could have the same problem. Try to check the header response for your POST, and see it is is a) empty, or b) not a 201.
On S3, you can modify your upload policy to return the correct response. Your policy should look something like this:
{
'expiration': '2008-12-31T12:00:00.000Z',
'conditions': [
{'bucket': 'my_test_bucket'},
{'key': 'test1.jpg'},
['starts-with', '$Filename', ''],
['eq', '$success_action_status', '201']
]
}
Note that the success_action_status is not an object property, but an [Operator, Operand, Operand] array.
Problem Solved? Not quite: still not uploads.
S3 Upload Example
Someone at AWS posted a helpful Flex -> S3 example, or actually examples. One Flex project creates and signs a policy, and the other uploads a file using the generated policy. And whats more, they both work. Also, took a look at the code to make sure it wasn't sending my AWS key/password off to some email! Ha. I think it was also posted by an AWS employee, so that is reassuring.
#2038 FileIOError
I kept getting a #2038 FileIOError on my mac. Bummer. Taking a closer look at the working AWS example, I saw a funny comment. Not funny roflcopter, but funny smelly bug-fixy.
/*
* FileReference.upload likes to send cryptic IOErrors when it doesn't get a status code that it likes.
* If we already got an error HTTP status code, don't propagate this event since the HTTPStatusEvent
* event handler dispatches an IOErrorEvent.
*/
As it turns out, I could NOT stop these #2038 FIleIOErrors. They just kept coming. But, as the example code reminded me, if you are getting a successful server response, the file is already up there. Sure enough, the file was there.
So you can pretty much ignore the FileIOError, although you should handle it, and just ignore it if you have a successful HTTP response, something like this:
private function onIOError(event:IOErrorEvent):void
{
if(!recievedSuccessfulHTTPresponse)
{
this.dispatchEvent(event);
}
}
You get the idea. Ok. Handle but ignore FileIOErrors. Done? Almost. Single uploads work, but I get an "Error #2044: Unhandled IOErrorEvent:. text=Error #2038: File I/O Error" when doing multiple uploads, via a FileReferenceList. Marvelous. This turned out to be even more of a pain. It wasn't anything to do with the server side upload script as my google searches might have me believe.
After brainstorming with a co-worker, we came to a pretty good guess: Garbage Collection. Maybe the FileReference was going out of scope before the IOError could be handled, or some such. PC/OS X differences in the runtime could have different GC implementations. Worth a shot. I changed my event listeners from "weak" to "strong" references. Shahooya. Multiple file upload city.
Other fixes
Make sure you have a publicly accessable crossdomain policy on the server you are uploading to.
Also, S3 scales well but adds extra complexity. You might try uploading to somewhere else, like a simple rails uploader.
Hope that helps. Also, please comment. In fact, today only, every commenter gets a free XBox. You know, its just a little lonely out here in the cloud sometimes.
