Friday, June 5, 2015

Building a User Avatar Component With Node.js & TransloadIt

In the first part of this series, we looked at TransloadIt — a file-processing service which specialises in processing images, videos and audio. If you haven’t read it yet, I’d urge you to do so now as it covers a lot of background concepts which you’ll need to understand in order to follow along with this part.

But enough of the reasoning, background and theory — let’s go through a practical example of how to use the service to handle some images in your own application.

For the purposes of this tutorial, we’re going to implement a user profile photo feature for an arbitrary application. We’ll use TransloadIt to do the following:

  1. Intercept the file upload, uploading it not to your application but to their servers.
  2. Perform server-side file checking, to ensure it meets certain criteria, such as whether it is indeed an image.
  3. Create a number of different derivatives — e.g. sizes — of the uploaded image, such as various sized thumbnails along with a “medium” and a “large” version for user profile pages.
  4. Transfer the resulting derivatives to an Amazon S3 bucket.
  5. Display a thumbnail of the newly-uploaded image in our application.
  6. Use the information returned from TransloadIt to let our application know where to find the resulting images, so that we can store a reference to them in the user records.

The first step is to build some templates containing assembly instructions.

Getting Started with Templates

A template contains assembly instructions in JSON format. Fire up your favourite text editor, begin some JSON:

[code language="js"] { } [/code]

… and let’s dive in.

Filtering Files

First we’ll add a step which utilizes the /file/filter robot to check the uploaded file’s MIME type, to ensure that it is an image. Add the following to your empty JSON document:

[code language="js"] "steps": "files": { "robot": "/file/filter", "accepts": [ [ "${file.mime}", "regex", "image" ] ], "error_on_decline": true }, [/code]

Let’s break this down.

We’re beginning with a step identified by the key files. You can call it what you want, but files makes sense in most cases.

Next we’re telling TransloadIt to use the /file/filter/ robot, which is used to perform some checks on the incoming files. In this case, we’re telling it what we want to accept; we ask it to extract the file’s MIME type and run a regular expression on it (image).

In TransloadIt instructions, a variable is denoted using a dollar sign and curly brackets ${}. When specifying a regular expression, you only need specify the main body of it.

Should the test we’re setting fail, the error_on_decline parameter ensures an error is thrown rather than continuing to the next step.

In other words, we’re telling TransloadIt to reject any files which aren’t images.

Adding Resizing Steps

Now let’s create three more steps, each doing much the same thing — creating a derivative (that is, a particular size) of the incoming images.

We can call the steps whatever we like, so we’ll use names which provide some context to the derivatives — medium, large and thumbnail.

Let’s define the first of these steps:

[code language="js"] "medium": { "use": ":original", "robot": "/image/resize", "width": 300, "height": 200, "resize_strategy": "fit" }, [/code]

Here we define a step named medium, which utilises the /image/resize robot. This takes a number of parameters, many of them optional, which are documented here.

The use parameter tells it to resize the original file.

In this case we’re providing the required dimensions — 300 by 200 pixels — as well as specifying a resize strategy. The available resize strategies are documented here, but essentially fit ensures that the image is resized to fit the specified dimensions, while preserving the aspect ratio.

The large step is virtually identical:

[code language="js"] "large": { "use": ":original", "robot": "/image/resize", "width": 480, "height": 320, "resize_strategy": "fit" }, [/code]

Then the thumbnail step:

[code language="js"] "thumbnail": { "use": ":original", "robot": "/image/resize", "width": 80, "height": 80, "resize_strategy": "crop" }, [/code]

This time we’re using the crop strategy to ensure we end up with an image which is perfectly square.

To make the process more efficient, there’s no reason why you can’t set the use parameter to tell TransloadIt to base the thumbnail on your already-processed large or medium versions.

At this stage, we’ve ensured that we’re dealing with an image, and we’re resized it three times over to create three separate image derivatives. Next up, we’ll tell TransloadIt what to do with the newly-created derivatives.

Export

As noted previously, Transloadit won’t store our files for long — hosting isn’t what the service is all about — so we need to move the files somewhere more permanent.

We’re going to use the /s3/store file export robot to upload the files to an Amazon S3 bucket.

Here’s how you might configure that step:

[code language="js"] "export": { "use": [ "medium", "large", "thumbnail" ], "robot": "/s3/store", "path": "users/profiles/${fields.username}_${previous_step.name}.${file.ext}", "key": "YOUR-S3-AUTH-KEY", "secret": "YOUR-S3-AUTH-SECRET", "bucket": "YOUR-BUCKET-NAME" } [/code]

You’ll need to replace your S3 credentials and bucket name with your own.

This is slightly more complex than our previous steps, so let’s break it down.

The use parameter tells the robot to run this step for each of our resized images, thus generating three files on S3 for every upload. As you can see, medium, large and thumbnail match the identifiers of our three previous steps.

Then we specify the key — S3’s term for a path — used to store the resulting files using the path configuration value. This, combined with the fully-qualified domain name of the bucket, later becomes the URI of the resulting derivative images.

In the example above, we’re using the following pattern:

[code language="js"] users/profiles/${fields.username}_${previous_step.name}.${file.ext} [/code]

This pattern begins by prefixing the path with users/profiles/, then uses the value of a hidden form field named username which we’ll define shortly. It then concatenates that with the key which defines the previous step, which is the name of our derivatives. Finally, it adds the extension of the original file, which is accesible via the variable ${file.ext}.

That’s quite a mouthful, so perhaps it’s best illustrated with an example. Given a username of bob, this pattern will produce the following three paths:

[code language="js"] users/profiles/bob_medium.jpg users/profiles/bob_large.jpg users/profiles/bob_thumbnail.jpg [/code]

There are all sorts of naming strategies you can employ, by chopping and changing the variables available to you. Foe example, consider the following pattern:

[code language="js"] users/profiles/${fields.username}${file.meta.width}x${file.meta.width}.${file.ext} [/code]

This dynamically constructs a filename by concatenating the username, the resulting file’s width and height, and finally the file’s extension. This will result in something like this:

[code language="js"] users/profiles/bob480x320.jpg [/code]

Continue reading %Building a User Avatar Component With Node.js & TransloadIt%


by Lukas White via SitePoint

No comments:

Post a Comment