How to add an image upload feature

We cannot store large files in MongoDB so we need to use Cloudinary to store media in their database.

What we need to do is;

  1. Setup our form to accept files
  2. Submit the form to hit one of our endpoints/routes
  3. Take the files and store in Cloudinary
  4. Cloudinary sends back URLs for the files
  5. We store the URLs in MongoDb

Multer Middleware

Default HTML forms accepts files but cannot send files.

In order to parse multipart forms we need to use the Multer middleware.

Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.
  1. Set HTML form to have enctype: multipart/formdata to accept files
  2. Add a file input into HTML form
  3. Install Multer middleware package
  4. Require Multer
  5. Add upload.single or upload.array to the route
  6. Now our form can pass files along

Environment Variables (.env)

Environment variable files are files we store data in such as API keys and secrets for tools so when we puch code public, that data is not accessible.

  1. Make a .env file in the top level of our app.
  2. Install dotenv package
  3. Add the following at the top of app.js which only requires and accesses our env file if in development mode so the public does not
    if(process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
    }
  4. Add our API keys into the .env file

Uploading to Cloudinary

  1. Install the Cloudinary and Multer Storage Cloudinary packages
  2. require and execute the packages in a cloudinary config file.
  3. Set the cloudinary.config options to associate our account details.
  4. Add a new instance of a cloudinary storage
  5. Require the storage variable in the relevant routes file
  6. Pass the storage as the destination in Multer

Storing Cloudinary image links in our MongoDB

  1. Update the images field in the relevent model to add filename and path
  2. Update the route by mapping over the array of files to connect the filenames to the model
    campground.images = req.files.map(f => ({
    url: f.path,
    filename: f.filename
    }))

List of sources

    Colt Steeles web developer bootcamp 2021