Upload and processing images to AWS S3 with Node JS using Multer and Jimp

If you want to change your image on the NodeJS server-side when uploading it to S3 — this article will help you do so

Zhabskyi
4 min readFeb 23, 2020

While I was working on my side project, I first faced the issue with uploading images to the AWS S3 bucket and later on I needed to add functionality to process images during this upload. For me, as a Junior Developer, it was a kind of journey to figure it out.

The article will be concise and include only the main information. This will be mostly coding examples from my project.

First of all, you need to install a dependency called Multer. Multer is a Node.js middleware for handling multipart/form-data, which is primarily used for uploading files.

Secondly, you need to install a dependency called Jimp. An image processing library for Node written entirely in JavaScript, with zero native dependencies.

You can find all the instructions on how to install them, basic usage cases and docs in those two top links.

Upload images in NodeJS with multer.

Step 1: Client-side consideration

Sending data to the server with your image file included must be a FormData. So, when I collected all data from inputs, I converted it to FormData and appended image file which I stored in the local state:

Client-side code

Step 2: Server-side consideration

Before proceed to work on file upload you will need some local variables:

AWS_BUCKET_NAME — the name of your S3 bucket;

AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY;

AWS_REGION — for example, “us-west-2”;

AWS_Uploaded_File_URL_LINK — you create by yourself and it has the format: https://s3-(your region).amazonaws.com/(bucket name)

Let's start to put code together:

First, you will need to import multer and AWS packages:

const multer = require('multer');
const AWS = require('aws-sdk');

After that create multer memory storage where you will upload the image to the buffer:

const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

When you do a post request for uploading photos, you need to run multer middleware:

router.post('/photos', upload.single('file'), async (req, res) => {
const info = req.body;
const image = req.file;
// Your code here
}

All your data information will contain in req.body, so you can pull it from there and your image will be in req.file with the following structure:

api_1       | Image {
api_1 | fieldname: 'file',
api_1 | originalname: 'cruise.jpg',
api_1 | encoding: '7bit',
api_1 | mimetype: 'image/jpeg',
api_1 | buffer: <Buffer ff d8 ff e1 3d 1e 45 78 69 66 00 00 49 49 2a 00 08 00 00 00 08 00 0f 01 02 00 05 00 00 00 6e 00 00 00 10 01 02 00 09 00 00 00 74 00 00 00 1a 01 05 00 ... 15755535 more bytes>,
api_1 | size: 15755585
api_1 | }

Now let's create S3 new instance and parameters which we need for uploading a file:

let s3bucket = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.AWS_REGION
});
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: image.originalname,
Body: file,
ContentType: image.mimetype,
ACL: 'public-read'
};

And finally uploading file to the bucket:

s3bucket.upload(params, async (err, data) => {
try {
if (err) {
res.status(500).json({ error: true, Message: err });
} else {
const newFileUploaded = {
description: info.description,
fileLink: s3FileURL + image.originalname,
s3_key: params.Key
};
info = { ...info, photo: newFileUploaded.fileLink };
const photos = await database.addPhoto(db, info);
res.send(photos);
}
} catch (err) {
res.status(500).json({ msg: 'Server Error', error: err });
}
});

Processing images in NodeJS with Jimp.

First, you will need to import Jimp package:

const Jimp = require('jimp');

Our image is in the buffer, where multer helped stored for us. So we need to read it first:

const file = await Jimp.read(Buffer.from(image.buffer, 'base64'))

You will get Promise, then we can process the image in the way how we want and store it into a variable:

.then(async image => {
const background = await Jimp.read('https://url/background.png');
const font = await Jimp.loadFont(Jimp.FONT_SANS_32_WHITE);
image.resize(Jimp.AUTO, 900);
image.composite(background, 1000, 700);
image.print(font, 1000, 700, 'Logo');
return image.getBufferAsync(Jimp.AUTO);
})

When the image been processed, you can upload it to AWS with multer.

Full NodeJs code you can find below:

NodeJS server-side

Hopefully, this information could help you if you straggled with NodeJS image work as I did.

--

--