Nextjs _middleware 带文件上传

发布于 2025-01-10 18:54:45 字数 3219 浏览 2 评论 0原文

我想将我的 Express 端点迁移到 vercel 无服务器功能。 我在express中的端点是这样的:

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

uploadMultiImages 是 multer 中间件:

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);

sendData 是我的控制器中接收请求的函数,检查 req.files 是否存在,如果存在,我提取 multer 提供的 Amazon 的 URL

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;
  }
}

:工作正常。但现在,我无法使用 Nextjs _middleware 复制此逻辑。

问题:

中间件代码在称为 Edge Runtime 的特殊运行时环境中运行,该环境很大程度上基于 Web API。您可能会注意到本机节点模块(例如 fs)在这些文件中将不可用。

嗯,multer 有一个名为“busboy”的依赖项,它使用“fs”。我收到一个错误。

所以我尝试做类似的事情> https://github.com/ leerob/nextjs-aws-s3/blob/main/pages/api/upload-url.js

但我无法理解它是如何工作的以及它是否真的可以帮助我。

我在 Next 中这个端点的文件夹结构是:

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

我还问自己,如何在 _middleware 函数中获取 req.files?

我错过了什么吗?是否可以使用 Nextjs 中的 _middleware 函数复制我在 Express 中所做的行为?

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文