sure @jahosh, I’ll see what I can post here that would be helpful.
A lot of this is from Slingshot tutorials.
# imports/startup/server/file-restrictions.js
Meteor.startup( () => {
Slingshot.fileRestrictions("myFileUploads", {
allowedFileTypes: ["image/png", "image/jpeg", "image/jpg", "image/gif"],
maxSize: 10 * 1024 * 1024 // 10 MB (use null for unlimited).
});
Slingshot.createDirective("myFileUploads", Slingshot.S3Storage, {
bucket: "[S3-BUCKET-NAME]",
acl: "public-read",
authorize: function () {
//Deny uploads if user is not logged in.
if (!this.userId) {
var message = "Please login before posting files";
throw new Meteor.Error("Login Required", message);
}
return true;
},
key: function (file) {
//Store file into a directory by the user's username.
// var user = Meteor.users.findOne(this.userId);
return file.name;
}
});
})
Then in my React component I have the following functions:
// [...]
import Dropzone from 'react-dropzone';
// [...]
onDrop(files) {
this.setState({ newImageLoaded: false });
// Upload file using Slingshot Directive
const uploader = new Slingshot.Upload('myFileUploads');
// Track Progress
const computation = Tracker.autorun(() => {
if (!isNaN(uploader.progress())) {
const progressNumber = Math.floor(uploader.progress() * 100);
this.setState({ progress: progressNumber });
if (progressNumber > 0 && progressNumber < 100) {
this.setState({ uploading: true });
} else {
this.setState({ uploading: false });
}
}
});
uploader.send(files[0], (error, url) => {
computation.stop(); // Stop progress tracking on upload finish
if (error) {
this.setState({ progress: 0 }); // reset progress state
this.setState({ uploadError: true });
} else {
// Wait until the Lambda script has finished resizing
this.checkResizedImage(url);
}
});
}
checkResizedImage(src) {
const { profile } = this.props;
const { uploadAttempts } = this.state;
const originalSrc = src;
const resizedImageSrc = src.replace('https://wtm-dev-images', 'https://wtm-dev-images-resized');
const cycleTime = 1000;
const img = new Image();
img.onload = function () {
// code to set the src on success
const newImage = {
profileId: profile._id,
image: originalSrc,
};
updateImage.call(
newImage
, displayError);
// Reset the upload counter in case the user tries again
this.setState({ uploadAttempts: 0 });
// Remove the Almost done... message
this.setState({ newImageLoaded: true });
};
img.onload = img.onload.bind(this);
img.onerror = function () {
const nextAttempt = uploadAttempts + 1;
this.setState({ uploadAttempts: nextAttempt });
// doesn't exist or error loading
if (uploadAttempts < 10) {
setTimeout(() => {
this.checkResizedImage(originalSrc);
}, cycleTime, originalSrc);
} else {
this.setState({ uploadError: true });
}
};
img.onerror = img.onerror.bind(this);
img.src = resizedImageSrc; // fires off loading of image
}
render() {
<Dropzone
onDrop={this.onDrop}
activeClassName="dropzone-target-active"
>
Text in the drop zone...
</Dropzone>
}
Then I just followed a Lambda tutorial about resizing images. I think it was this one: http://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html
Basically Slingshot just puts the full image on one bucket, and lambda reacts to the bucket event and puts the altered image on another bucket. I manually alter the path to point to the new bucket and the this.checkResizedImage()
function waits until that image is ready and writes it back to the database.
Hope that helps! If I’m missing anything let me know and I’ll post it.