Uploading the avatar photo to contacts

Let's start by creating the endpoint to upload avatar photos:

// routes.js
var controller = require('./controller');

//...
server.post('/api/contacts/:contactId/avatar', 
controller.uploadAvatar);

Express itself does not process files automatically; it needs a plug-in that transforms the raw request into a more user-friendly API. This plug-in is named multer; it processes multipart/form-data, saving the file into a temporary path or making a buffer object, and then provides a JSON object with metadata information:

// Avatar endpoints
var upload = multer();
server.post('/api/contacts/:contactId/avatar', upload.single('avatar'),
controller.uploadAvatar
);
server.use('/avatar', express.static(__dirname + '/avatar'));

With the default configuration, it will save all the uploaded files into the temporary path of your operating system, which is /tmp in Unix systems; multer will attach a files attribute in the req object, which we can inspect to retrieve information about the uploaded files:

uploadAvatar(req, res, next) {
varcontactId = req.params.contactId;
var filename, fullpath;

  // Ensure that user has sent the file
  if (!_.has(req, 'file')) {
    return res.status(400).json({
      error: 'Please upload a file in the avatar field'
    });
  }

  // File should be in a valid format
var metadata = req.file;
  if (!isValidImage(metadata.mimetype)) {
res.status(400).json({
      error: 'Invalid format, please use jpg, png or gif files'
    });
    return next();
  }

  // Get target contact from database
var contact = _.find(contacts, 'id', contactId);
  if (!contact) {
res.status(404).json({
      error: 'contact not found'
    });
    return next();
  }

  // Ensure that avatar path exists
  if (!fs.existsSync(AVATAR_PATH)) {
fs.mkdirSync(AVATAR_PATH);
  }

  // Ensure unique filename to prevent name colisions
var extension = getExtension(metadata.originalname);
  do {
    filename = generateFilename(25, extension);
fullpath = generateFullPath(filename);
  } while(fs.existsSync(fullpath));

  // Remove previous avatar if any
removeAvatar(contact);

  // Save the file in disk
varwstream = fs.createWriteStream(fullpath);
wstream.write(metadata.buffer);
wstream.end();

  // Update contact by assingn the url of the uploaded file
contact.avatar = {
    file: filename,
url: generateURLForAvatar(filename)
  };

res.json({
    success: true,
    avatar: contact.avatar
  });
}

In the first steps, we validate that user has been uploaded a valid file and then we get the target user from the database and, if doesn't exist, we return an Http 404 error. The multer plug-in stores the uploaded file in memory, and can be processed before saving the file to the final path; for example, maybe we want to generate a thumbnail file or process the image to save space on disk.

We ensure that the avatar path exists; if doesn't we then create the path. In the next steps, we generate a filename to be assigned to the uploaded file in order to prevent filename collisions; the generateFilename() function generates that filename and then checks if it already exists; if it does, then we generate another filename and so on.

Once we have a unique filename for the uploaded file, we store the file from the in-memory buffer to the generated path. Now that the file is in the avatar path, we can build the URL where we can get the image from the browser, and finally assign the URL to the avatar field in the contact resource.

Showing the avatar

Now that we can upload images and the contact resource has the information about where the avatar is located, we can show the avatar in our views by pointing an img tag to the avatar.url property in the Contact model:

<% if (avatar && avatar.url) { %>
<imgsrc="<%= avatar.url %>" alt="Contact photo" />
<% } else { %>
<imgsrc="http://placehold.it/250x250" alt="Contact photo" />
<% } %>

This will show the image, if any; otherwise it will show a default one. We should modify the Contact model to include a default avatar:

// apps/contacts/models/contact.js
'use strict';

var Backbone = require('backbone');

class Contact extends Backbone.Model {
// ...

  get defaults() {
    return {
      name: '',
      phone: '',
      email: '',
      address1: '',
      address2: '',
facebook: '',
      twitter: '',
      google: '',
github: '',
      avatar: null
    };
  }

// ...
}

module.exports = Contact;

If no avatar image is retrieved from the server, then we use a null image. The following screenshot shows how it looks like when you upload an image. This is enough to show an avatar image where it's necessary. It is very easy to show images. In the rest of the chapter, we will see how to perform the upload:

Showing the avatar

Figure 5.2 Showing the Contact avatar

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.141.27