首页 > 解决方案 > Nodejs - 如何在不使用像 multer 这样的中间件的情况下将从前端发送的文件对象保存到公用文件夹?

问题描述

我有一个 React 客户端应用程序和一个 Nodejs 后端。

我正在尝试在这样的 put 请求中将字符串化的 json 和一些 pdf 文件(通过react-dropzone从客户端上传)作为 formdata/multipart 发送:

let formData = new FormData()

formData.append('user', JSON.stringify(jsonData))
formData.append('file_1', user.file_1)
formData.append('file_2', user.file_2)

在我的 Nodejs 后端,我使用 multer 提取表单数据:

let multerInstance = multer();
userRouter.put('/user/:user_id', validateJwt, multerInstance.any(), putUser);

我像这样提取formdata:

const formData = req.body;
const user = JSON.parse(formData.user);
const files = req.files; // here I have file_1 and file_2 as file objects

但是,如果我使用 multer 保存文件,我必须像这样在中间件中传递配置设置:

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './public/uploads');
  },
  filename: function (req, file, cb) {
    var fileFormat = file.originalname.split('.');
    cb(null, file.fieldname + '-' + Date.now() + '.' + fileFormat[fileFormat.length - 1]);
  },
});

let multerInstance = multer({
  storage: storage,
});

let multerInstance = multer();
userRouter.put('/user/:user_id', validateJwt, multerInstance.any(), putUser);

我不想这样做,因为我想决定是否在 putUser 中执行上传操作(保存到 /public/uploads),而不是在 multer 中间件中设置目标(无论如何,它将在 putUser 之前运行)

我怎样才能做到这一点?

标签: node.js

解决方案


很高兴找到解决方案fs.writeFile

首先,在没有任何配置的情况下在这样的路由上使用 multer,以便它仅用作 formdata 移相器:

let multerInstance = multer();
userRouter.put('/user/:user_id', validateJwt, multerInstance.any(), putUser);

接下来,获取req.files路径中的文件,分阶段的文件multer将如下所示:

{
    fieldname: 'myField',
    originalname: 'file_1.pdf',
    encoding: '7bit',
    mimetype: 'application/pdf',
    buffer: <Buffer 25 50 44 46 2d 31 2e 33 0a 25 c4 e5 f2 e5 eb a7 f3 a0 d0 c4 c6 0a 34 20 30 20 6f 62 6a 0a 3c 3c 20 2f 4c 65 6e 67 74 68 20 35 20 30 20 52 20 2f 46 69 ... 51728 more bytes>,
    size: 51778
}

由于我观察到文件中有一个缓冲区,我可以使用模块将文件写入目标路径,fs以便可以在路由内完成上传操作。

const files = req.files

const uploadFiles = files.map((file) => {
   return new Promise(function (resolve, reject) {
       let fileFormat = file.originalname.split('.');
       let savePath = file.fieldname + '-' + Date.now() + '.' + fileFormat[fileFormat.length - 1];
       fs.writeFile('./public/uploads/' + savePath, file.buffer, function (err) {
         if (err) {
            return reject();
         }

         return resolve();
      });
   });
});

await Promise.all(uploadFiles);

推荐阅读