- [Narrator] By now, we have a buffer
that contains our image data
and some meetup information for the image.
In this video, we will convert the image to PNG,
to not having to deal with different file formats,
and we shrink the image to a maximum size needed
on our page to save some disk space.
There are several modules that deal
with image manipulation available;
I personally prefer sharp.
It provides plenty of image manipulation methods
and a good performance.
So let's install it now by running npm install --save sharp,
and we will need image manipulation functions
on different places,
so it makes sense to create this service class for that.
So I will now go into server, services,
and there I create a new file: AvatarService.js.
There, of course, first,
bring const sharp = require('sharp'),
and we need need a few more modules,
because I want to automatically create file names.
For that, we will use uuidv4 = require('uuid'),
and we take the version four here,
and we need util,
and also we will need path to deal with file path,
and also because we are dealing with files,
we will need file system methods, so I add require('fs').
Next, as we want to use unlink to delete files later,
I will create a promisified version of unlink,
so I call is fsunlink, which is util.promisify(fs.unlink),
so this will wrap this function to return a promise.
Now let's start implementing the class,
so I add a class AvatarService.
And let's fix the indents real quick,
so I'm using two spaces here.
And first, let's implement a constructor,
and this constructor gets a directory;
that's the directory where we want to store files,
and then I create a member variable from it:
this.directory = directory.
Next, we need a function that does the storing of the file,
and also the resizing, so add a new function, async store,
and this function will take a buffer from alter.
And I also want to create two little helper functions;
first is static filename(),
and this will simply create a file name for us.
And in return, a uuidv4 string,
and we take the extension .png,
because will create PNG files.
And I will also create a new helper function filepath,
which takes a filename,
and returns the full path to this file,
path.resolve, and in there, I use this.directory;
that's the directory from the constructor, and /$(filename).
Now back to our store function;
we can now add const filename = AvatarService,
so because it's a static method,
because it does not contain any reference
to the class via this AvatarService.filename,
and we also want to create the filepath now,
const filepath = this.filepath,
and we path in the previously created file name.
Now comes the logic to actually resize and store the image,
so I add await sharp, and we path in the buffer,
and then we call the resize method on it,
and we want to resize it to 300 times 300,
and we have to add a few config arguments here,
because we want it to fit these constraints,
sharp.fit.inside.
And we also don't want these images to be enlarged,
because enlarging images
always means a loss of image quality.
And, in the end, we want to store it to the event filepath.
And to work with the file that was just created,
we will return the file name to a color.
Next, I also want to create a function
that can delete images.
For that, I add async, delete, some filename,
and this will run if it's unlinked;
it's not promisified,
unlink function this.filepath(filename).
In the end, we should not forget to export from this module,
so add module.exports = AvatarService.
This should give us all functionality we need for now,
and I've created a test that verifies that
to around npx mocha,
test/server/services/AvatarService.test.js,
and we see that it can deal with PNG images, JPEG images,
and it can also delete images.