Handling Files using MongoDB Stitch and AWS S3

Aydrian Howard

mongodb
Facebook ShareLinkedin ShareReddit ShareTwitter Share

MongoDB is the best way to work with data. As developers, we are faced with design decisions about data storage. For small pieces of data, it’s often an easy decision. Storing all of Shakespeare’s works, all 38 plays, 154 sonnets, and poems takes up 5.6MB of space in plain text. That’s simple to handle in MongoDB. What happens, however, when we want to include rich information with images, audio, and video? We can certainly store that information inside the database, but another approach is to leverage cloud data storage. Services such as AWS S3 allow you to store and retrieve any amount of data stored in buckets and you can store references in your MongoDB database.

With a built-in AWS Service, MongoDB Stitch provides the means to easily update and track files uploaded to an S3 bucket without having to write any backend code. In a recent Stitchcraft live coding session on my Twitch channel, I demonstrated how to upload a file to S3 and record it in a collection directly from a React.js application. After I added an AWS Service (which just required putting in IAM credentials) to my Stitch application and set up my S3 Bucket, I only needed to add the following code to my React.js application to handle uploading my file from a file input control:


handleFileUpload(file) {
 if (!file) {
   return
 }

 const key = `${this.client.auth.user.id}-${file.name}`
 const bucket = 'stitchcraft-picstream'
 const url = `http://${bucket}.s3.amazonaws.com/${encodeURIComponent(key)}`

 return convertImageToBSONBinaryObject(file)
   .then(result => {
     // AWS S3 Request
     const args = {
       ACL: 'public-read',
       Bucket: bucket,
       ContentType: file.type,
       Key: key,
       Body: result
     }

     const request = new AwsRequest.Builder()
       .withService('s3')
       .withAction('PutObject')
       .withRegion('us-east-1')
       .withArgs(args)
       .build()

     return this.aws.execute(request)
   })
   .then(result => {
     // MongoDB Request
     const picstream = this.mongodb.db('data').collection('picstream')
     return picstream.insertOne({
       owner_id: this.client.auth.user.id,
       url,
       file: {
         name: file.name,
         type: file.type
       },
       ETag: result.ETag,
       ts: new Date()
     })
   })
   .then(result => {
     // Update UI
     this.getEntries()
   })
   .catch(console.error)
}

To watch me put it all together, check out the recording of the Stitchcraft live coding session and check out the link to the GitHub repo in the description. Be sure to follow me on Twitch and tune in for future Stitchcraft live coding sessions.

-Aydrian Howard
@aydrianh
Developer Advocate
NYC