S3 browser upload via POST: unable to handle errors gracefully
I am writing an app where I want the customer to be able to upload to Amazon S3 straight from开发者_运维知识库 the browser. I can make this work just fine. But when errors occur, I want to handle them more gracefully than splattering an XML document on the customer's screen.
I have a scheme that I think would work, but it's failing. Here's what I'm trying:
- Create a form to do the upload, and store the form on S3 itself, in the same domain as the "action" attribute of the form.
- Redirect the customer to this form. Now their browser is sitting on https://<bucket>.s3.amazonaws.com/something.
- The page contains a hidden iframe. The form sets its target to the iframe.
- The load event handler looks at the contents of the iframe, and acts upon it.
So, something like this:
<iframe id="foo" name="foo" style="display: none" />
<form target="foo" action="https://<bucket>.s3.amazonaws.com/">
<input type="hidden" name="..." value="..." />
<input type="file" name="file" />
</form>
with this javascript (using jquery):
function handler() {
var message = $("#foo").contents().find('message').text();
alert(message);
}
$("#foo").load(handler);
Using firebug, I can see that the iframe contains an XML document, that contains a "message" node. However, the .find('message')
always fails to find anything within the XML document.
Notice that the action of the form has the same domain, port, and scheme as the document itself. So, I don't think that I should be running afoul of the same-origin policy. Right? But it fails every time. This is using Firefox and Google Chrome browsers.
Thanks for any advice!
There are a number of jQuery plugins that effectively implement exactly what you are trying to do. Do a Google search for "jQuery ajax-upload", you could just use one of these controls out of the box to capture the result of the post or examine their code and roll your own.
You may also want to look into some of the Flash based uploaders if you are uploading large files. The pure form method of uploading does not have any way of implementing an upload progress, at least not until the new file functions are wide spread in browsers, which Flash does offer. http://github.com/slaskis/s3upload#readme is a good flash based file uploader specifically designed for S3 and gives you call back functions in JavaScript to handle errors, progress and more.
This should be just a comment, but can you post the response XML code?
EDIT: Just to narrow down a little, i made a simple test and worked really fine:
<div id="foo">
<error>
<code>AccessDenied</code>
<message>Invalid according to Policy: Policy expired.</message>
<hostid> SZuQn5hTyf32j79AWUym1/si48oqjPifrx4goDVDLYYxc6cJVbbHroLJYcAM89+T</hostid>
</error>
</div>
Then I did some jQuery code on my firebug:
$("#foo").find("message").text()
Maybe you can give an alert($("#foo").html())
and check the response..
I think that you're trying to solve the wrong problem. The problem is not a detail one, with iframes and such, but that you want to have finer control over the upload. Upload the file to your server, then submit a request to the Amazon server, and you'll have absolute control over what's going on.
Significantly more complex, of course, but that's the price of control.
精彩评论