Reputation: 2908
In a meteor app what is the best way to get images from aws s3? I've tried three ways but all have issues.
Method 1 : Common solution
Problem: The img tag loads with the string http://s3.amazonaws.com/etc...
before {{copies.original.key}}
kicks in. This shows a broken image icon while the image loads.
client.js
Template.newProduct.helpers({
'image': function(){
newImages = // logic here;
return Images.find({'_id':{'$in':newImages}});
}
});
template.html
<template name="newProduct">
{{#each image}}
<img src="http://s3.amazonaws.com/etc...{{copies.original.key}}">
{{/each}}
</template>
Method 2 : Loop over each image get the url and serve it in an array to blaze {{#each image}}
Problem: Whenever an image gets added this function gets run again and the images have to be re-loaded. Causing a long flicker as one updates. I only want to load the new image.
client.js
Template.newProduct.helpers({
'image': function(){
newImages = // logic here;
x = Images.find({'_id':{'$in':newImages}});
var returnArray = [];
for(i=0;i<x.count();i++){
stringResult = "http://s3.amazonaws.com/etc..." + x.fetch()[i].copies.original.key;
returnArray.push(stringResult);
}
return returnArray;
}
});
template.html
<template name="newProduct">
{{#each image}}
<img src="{{this}}">
{{/each}}
</template>
Method 3 : On file upload use js to construct an image tag and add it to the page.
Problem: When you load images from another website this way it causes a 403 (forbidden) error. You can't load images like this on the fly.
'change .in': function(ev, t) {
FS.Utility.eachFile(ev, function(file) {
Images.insert(file, function (e,f) {
if (!e){
$('#imageShack').append($('<img />').attr('src', 'http://s3.amazonaws.com/etc..' + f._id + '-' + f.original.name));
}
});
});
}
Upvotes: 0
Views: 704
Reputation: 19153
I think you have fully identified the problem when you say:
Problem: The img tag loads with the string http://s3.amazonaws.com/etc... before {{copies.original.key}} kicks in. This shows a broken image icon while the image loads.
The way avoid this is either
Both these solutions will fix your problem because they deliver the url in its complete and unbroken form.
template.html
<template name="newProduct">
{{#each image}}
<img src="{{copies.original.s3Url}}">
{{/each}}
</template>
template.html
<template name="newProduct">
{{#each image}}
<img src="{{getImageUrl copies.original.key}}">
{{/each}}
</template>
client.js
Template.newProduct.helpers({
'image': function(){
newImages = // logic here;
return Images.find({'_id':{'$in':newImages}});
}
'getImageUrl': function(key){
return 'http://s3.amazonaws.com/etc...' + key;
}
});
Personally I would favour solution #1.
When I upload images to s3 I store the full url (including the bucket name) as this is, in effect, the complete identity of that image version.
The image key is only a part of the identity and if you rely on a partial identity you will nearly always end up with additional complexity.
Upvotes: 1