Nextjs _middleware 带文件上传
我想将我的 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论