> Would you mind posting your solution for S3?
We took advantage of S3's recently-announced support for Cross-Origin
Resource Sharing (CORS):
http://aws.typepad.com/aws/2012/08/amazon-s3-cross-origin-resource-sharing.html
Once you add an appropriate CORS configuration to one of your S3
buckets, it becomes possible to post images directly from JavaScript
to S3 without an intermediate proxy server.
I started with the following walk-throughs:
http://bencoe.tumblr.com/post/30685403088/browser-side-amazon-s3-uploads-using-cors
http://stackoverflow.com/questions/11240127/uploading-image-to-amazon-s3-with-html-javascript-jquery-with-ajax-request-n
Neither of these quite covered my use-case of uploading webcam images
from Chrome directly to S3, though, so I'll provide some additional
details in hopes that someone will find them helpful.
For reference, the policy I sent with each POST request ended up
looking something like this:
{"expiration": "2012-12-31T00:00:00Z",
"conditions": [
{"bucket": "<CORS_ENABLED_S3_BUCKET>"},
{"acl": "public-read"},
{"Content-Type": "image/png"},
["starts-with", "$key", "<DESIRED_KEY_PREFIX>/"],
["content-length-range", 0, <MAX_LENGTH>]
]
}
I found it necessary to use a lower-case bucket name to get this policy to work.
I ran something like the Python script included in the article below
locally to encode the policy above and generate a signature for it
each time I edited it:
http://aws.amazon.com/articles/1434
I then copied the encoded policy and signature (which are safe to
distribute) into my JavaScript code.
Since the images I wanted to POST were being captured by a webcam,
saved to a canvas, and exported in a base64-encoding via toDataURL, I
needed a few additional tricks to convert them back to actual image
files on their way to S3.
A sidenote: a friend helped me discover the necessity of setting the
width and height of the canvas explicitly immediately before exporting
an image with toDataURL. This issue only appeared when we upgraded
from Chrome 21 to Chrome 22, and I'm still not sure exactly when and
why Chrome began resetting our canvas size to zero, but the explicit
reassignment before attempting to capture a video frame was a
sufficient workaround.
I included the following patch in my JavaScript to add a sendAsBinary
method to the XMLHttpRequest implementation in the versions of Chrome
I was using:
http://code.google.com/p/chromium/issues/detail?id=35705#c39
Before each upload, I first stripped the type prefix from the dataURL:
data = dataURL.replace('data:' + 'image/png' + ';base64,', '');
I wasn't able to get the FormData approach of the walkthroughs above
to convert my base64-encoded image back to binary, so I ended up
building my POST request myself roughly as follows:
--------------------------------------------------------------------
var aws_base_url = 'https://<CORS_BUCKET>.
s3.amazonaws.com/';
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", function (e) {uploadComplete(e [,
<OTHER_PARAMS…>]);}, false);
xhr.open('POST', aws_base_url, true);
var boundary = 'WebKitFormBoundary<EXTRA_RANDOM_STRING>';
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary='
+ boundary);
upload_data = [
'--' + boundary,
'Content-Disposition: form-data; name="key"',
'',
key,
'--' + boundary,
'Content-Disposition: form-data; name="acl"',
'',
'public-read',
'--' + boundary,
'Content-Disposition: form-data; name="Content-Type"',
'',
type,
'--' + boundary,
'Content-Disposition: form-data; name="AWSAccessKeyId"',
'',
'<AWS_ACCESS_KEY_ID>',
'--' + boundary,
'Content-Disposition: form-data; name="policy"',
'',
'<ENCODED_POLICY>',
'--' + boundary,
'Content-Disposition: form-data; name="signature"',
'',
'<SIGNATURE>',
'--' + boundary,
'Content-Disposition: form-data; name="file"',
'',
atob(data),
'--' + boundary + '--'
].join('\r\n');
console.log("Length of upload_data: " + upload_data.length);
xhr.sendAsBinary(upload_data);
--------------------------------------------------------------------
I believe the 'key' parameter has to appear first and the 'file'
parameter has to appear last; AWS may also be sensitive to the order
of the other parameters. I found the raw POST request examples here
very helpful:
http://docs.amazonwebservices.com/AmazonS3/latest/dev/HTTPPOSTExamples.html
Once the webcam images were uploaded, I wanted them to appear
automatically in the Meteor interface in a reverse-chronological image
feed without broken image icons, slowly-loading images, or flicker,
but I haven't yet implemented the ideal solution. My initial approach
was to have the uploadComplete handler set a flag in the database
record corresponding to each freshly-uploaded photo and for the
template to display only the photos that had this flag set. However,
this still occasionally elicits 403 errors from AWS, possibly because
an image has been uploaded but isn't quite available for downloading
yet, and it's often possible to see individual images drawn
progressively as they are re-downloaded on a slow connection.
It would probably be better to preload the images from S3 and only set
the flag when they have been downloaded completely. Better still would
be some mechanism for feeding the local copy of the webcam image to
the template as a placeholder when possible and having it seamlessly
fall back to a preloaded remote copy of the image otherwise.
Thanks for reading this lengthy post -- I hope you find it useful!
Zak
> On Sunday, September 30, 2012 11:08:36 AM UTC-7, Zak wrote:
>>
>> Hello everyone,
>>
>> I'm excited that discussions are underway about managing binary data
>> with Meteor, and I'd like to share a use-case and some of the issues
>> we encountered in our initial attempts to use Meteor to work with
>> image data.
>>
>> ------------
>>
>>
>> We've since adapted our code to post images directly to S3 and manage
>> references to those images with Meteor, but it would be fantastic if
>> Meteor could handle use-cases like this natively in the future.
>>
>> Thanks,
>> Zak
>
> --
> You received this message because you are subscribed to the Google Groups
> "meteor-talk" group.
> To view this discussion on the web visit
>
https://groups.google.com/d/msg/meteor-talk/-/Gst-SEAbHt8J.