Next.js: file/image upload using api route (pages/api)

This post help you figure out how to post a binary file (image/file) via api route using formidable.
Making Next.js just pass the file from front-end as it is to the back-end does not work!
You need to do modify the file in the api route before sending to the back.

Next.js: 13.0.6
Node.js: 16.17.1

plantUML

pages/upload.tsx

This is the brief overview of the front-end code.

const response = await axios.post(
    '/api/upload',
    {
      file,
      title: 'sample title'
    },
    {
      headers: {
        'content-type': 'multipart/form-data',
      },
    }
  );

pages/api/upload.tsx

First, you need to disable body parsing in Next.js by this.
https://nextjs.org/docs/api-routes/request-helpers

export const config = {
  api: {
    bodyParser: false,
  },
};

Then, parse the file data using formidable.

The parsed data is passed to the api call as a parameter: file has file object, whilefields has non-file request parameters.

The file object is conveted to a readable stream by fs.createReadStream().

import { IncomingForm } from 'formidable';
import fs from 'fs';
import { NextApiRequest, NextApiResponse } from 'next';

export const config = {
  api: {
    bodyParser: false,
  },
};

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
  const form = new IncomingForm();
  form.parse(req, async (err, fields, files: any) => {
    try {
      const { data } = await axios.post(
        `${END_POINT_OF_BACKEND}`,
        { ...fields, file: fs.createReadStream(files.file.filepath) },
        {
          headers: {
            'content-type': req.headers['content-type'],
          },
        }
      );
      res.send(data);
    } catch (e: any) {
      res.status(e.status ?? 500).json(e);
    }
  });
};

export default handler;