Nextjs _middleware with file upload

Viewed 610

I want to migrate my express endpoint to vercel serverless function. My endpoint in express is something like that:

router.route('/lead').post(uploadMultiImages, sendData);

uploadMultiImages is multer middleware:

import path from 'path';
import multerS3 from 'multer-s3';
import multer from 'multer';
import S3 from 'aws-sdk/clients/s3';

const config = {
  accessKeyId: process.env.AWS_S3_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_S3_SECRET_ACCESS_KEY,
  region: 'eu-west-1',
};

const multerFilter = (req: any, file: any, cb: any) => {
  if (
    file.mimetype === 'image/jpeg' ||
    file.mimetype === 'application/msword' ||
    file.mimetype ===
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ||
    file.mimetype === 'application/pdf' ||
    file.mimetype === 'image/png'
  ) {
    cb(null, true);
  } else {
    cb(new Error('Not an image! Please upload images only.'), false);
  }
};

const s3 = new S3({});

s3.config.update(config);

export const uploadMultiImages = multer({
  storage: multerS3({
    s3,
    bucket: 'bucket-name',
    acl: 'public-read',

    key: function (
      _req: any,
      file: { originalname: string },
      // eslint-disable-next-line no-unused-vars
      cb: (arg0: null, arg1: string) => void
    ) {
      cb(
        null,
        path.basename(file.originalname, path.extname(file.originalname)) +
          '-' +
          Date.now() +
          path.extname(file.originalname)
      );
    },
  }),
  fileFilter: multerFilter,
}).array('file_upload', 12);

The sendData is a function in my controller that receives the request, check if the req.files exists and if it does, I extract the Amazon's URL provided by multer:

import { Request, Response } from 'express';
import { postFormData } from '@services/api/crm';

export async function sendData(req: Request, res: Response) {
  
  try {
    const formData = req.body;

    if (!req?.files || req?.files?.length === 0) {
      res.json({ data: formData, message: 'No file selected' });
     
    } else {
      const fileArray = req?.files as any[];

      const galleryImageLocationArray = fileArray?.map((el) => el.location);
      formData.attachment = galleryImageLocationArray.join(';');

      res.status(200).json({
        filesArray: fileArray,
        locationArray: galleryImageLocationArray,
      });

    }
    await postFormData(formData);  // it does the post request to the CRM passing data
  } catch (err: any) {
    console.log('something wrong', err);
    throw err.response?.data;
  }
}

And it works fine. But now, I'm not able to replicate this logic with Nextjs _middleware.

Problem:

Middleware code runs in a special runtime environment known as the Edge Runtime, which is heavily based on Web APIs. You might notice that native node modules (e.g. fs) will not be available/usable in these files.

Well, multer has a dependency called "busboy" that use 'fs'. And I get an error.

So I tried to do something like that > https://github.com/leerob/nextjs-aws-s3/blob/main/pages/api/upload-url.js

But I can't understand how it works and if it could actually help me.

My folder structure for this endpoint in Next is:

-pages
   -api
      -lead
         index.ts
         _middleware.ts

I also asked myself, how can I get req.files in the _middleware function??

Am I missing something? Is it possible to replicate the behaviour I did in Express with this _middleware function in Nextjs?

Thanks

0 Answers
Related