Create a Custom Multer Storage Engine to upload images with placeholders to S3 for Next.js Image Component

Larbi Sahli
3 min readNov 2, 2022

--

We want the user to know that images are still fetching on the server and provide some feedback as soon as possible when the page is not fully loaded. Some websites, such as Unsplash, have blur image placeholders, which adds some aesthetic to the website.

In this blog, we will go through how to create a custom Multer Storage Engine to upload an image and generate a placeholder for it, we will also create a custom Next.js Image component to show our blurred placeholder.

Multer has three types of Storage

  1. Disk Storage
  2. Memory Storage
  3. Custom Storage

Disk storage:
The disk storage engine gives you complete control over storing files on your disk.

Memory storage:
The memory storage engine stores the files in memory as Buffer objects. It doesn’t have any options.

Custom Storage (Own Multer Storage Engine):
Storage engines are classes that expose two functions: _handleFile and _removeFile.

Creating the Multer Storage Engine

We are going to use the following packages to build our application:

  • express: A very popular Node server.
  • multer: A package for extracting files from multipart/form-data requests.
  • jimp: An image manipulation package.
  • dotenv: A package for adding .env variables to process.env.
  • aws-sdk: A package for uploading and downloading images from an s3 bucket.
  • concat-stream: A package for creating a writable stream that concatenates all the data from a stream and calls a callback with the result.
  • streamifier: A package to convert a Buffer/String into a readable stream.

Let’s create a new file in our project root named storage.ts, inside it, the file should contain the following blueprint code snippet:

The _handleFile function is responsible for uploading the image and its placeholder to the s3 bucket, and then returning information on how to access the file path in the future.
The information we provide in the callback will be merged with multer’s file object, and then presented to the user via req.file since we only allow one file per request.

Your storage class must implement the _removeFile function. this function is also responsible for removing files if an error is encountered later on. Multer will decide which files to delete and when. It will receive the same arguments as _handleFile, and invoke the callback once the file has been removed.

Create a server.ts file to use our storage engine

The Multer Storage Engine creates the handler for the upload request. We are going to implement the /upload route to actually handle the upload and /media route to handle the download.

Next.js Image Component

Now our server is ready to upload and download images, let’s create our Image component

After we upload our image we received a response with the image path and its placeholder. Let’s create a hook useGetDataUrl to Fetch the blob and convert the placeholder to base64 for the Next.js Image Component.

I hope this help add some aesthetics to your website.
Complete code: GitHub

--

--

Larbi Sahli

Full Stack Engineer | React | Next.js | Typescript | GraphQL | PostgreSQL, I love open source and startups.