ExpressJS:req.body 值以字符串形式出现“[object Object]”

ExpressJS: req.body value comes as a string "[object Object]"

我正在尝试让 multer 在我的后端工作,以便能够处理文件。 我从 Angular 9+ 前端发送 (POST) 一个 FormData 对象到我的后端,看起来像:

foo: 'test',
bar: { id: 'someId', name: 'someName' },
file: { SOMEFILE }

在我的后端我有一个 server.js 文件:

const path = require('path');
const express = require("express");
const cors = require('cors');
const bodyParser = require("body-parser");
const mongoose = require('mongoose');

const app = express();

// SOME ROUTE IMPORTS -- Just the variable pointing to the route.


app.use(cors());

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

mongoose.connect(uri, {
    useNewUrlParser: true, 
    useUnifiedTopology: true,
    useFindAndModify: false,
    useCreateIndex: true
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB Connection Error:'));

// THERE I "USE" THE PREVIOUSLY IMPORTED ROUTES: app.use(routeX);

和有问题的路由文件(我们称之为 routeX):

const express = require('express');
const router = express.Router();
const multer = require('multer');

const MIME_TYPE_MAP = {
    'image/png': 'png',
    'image/jpeg': 'jpeg',
    'image/jpg': 'jpg',
    'application/pdf': 'pdf'
}

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        const isValid = MIME_TYPE_MAP[file.mimetype];
        let error = new Error("Invalid mimeType");
        if (isValid) {
            error = null;
        }
        cb(error, "docLibrary/equipment/");
    },
    filename: (req, file, cb) => {
        const dateNow = Date.now();
        const name = dateNow + '-' + file.originalname.toLowerCase().split(' ').join('_') + '-' + file.fieldname;
        const ext = MIME_TYPE_MAP[file.mimetype];
        cb(null,name + '.' + ext)
    }
});

const upload = multer({storage: storage});
const cpUpload = upload.fields([{name: 'proforma', maxCount: 1}, {name: 'technicalDetails', maxCount: 1}]);

router.post('/newEquipment', cpUpload, async (req, res, next) => {
    const url = req.protocol + '://' + req.get('host') + '/';
    let receivedEquip = req.body;
    console.log('receivedEquip\n');
    console.log(JSON.stringify(receivedEquip));
    console.log('\n');
}

问题是 console.log 函数为 req.body 提供了以下 JSON:

"foo": 'test',
"bar": "[object Object]",

"bar" 由于某种原因变成了一个 String 对象,它指定了它的值的类型...... 我觉得这是因为 multer 以及我正在发送 FormData 的事实,但我不确定在这里看哪里...... 有任何想法吗 ?

好的,试试这个;

router.post('/newEquipment', cpUpload, async (req, res, next) => {
const url = req.protocol + '://' + req.get('host') + '/';
let receivedEquip = JSON.parse(JSON.stringify(req.body));
let uploadFile = req.files.file  // to get the file from the formData
console.log('receivedEquip\n');
console.log(receivedEquip);
console.log('\n');

});

好吧,毕竟它很愚蠢...... 我不熟悉 FormData 对象,此时我希望有更好的方法将 blob 发送到后端。 不确定它是否存在,所以目前,解决方法是这样的:

问题的来源:

正如我们的好朋友 VSCode 所提到的 - FormData 不接受对象作为值。只有 Blobsstrings

Argument of type '{ test: string; secondTest: string; }' is not assignable to parameter of type 'string | Blob'.
  Object literal may only specify known properties, and 'test' does not exist in type 'Blob'.ts(2345)

解决方案

因此,当附加到 FormData 时,您所要做的就是将 JSON Object 字符串化:

if (typeof currFormValue[key] === 'object') {
              const currObject = JSON.stringify(currFormValue[key])
              someFormDataObject.append(key, currObject);
            }

并在服务器上将这些字段再次解析为 JSON,如下所示:

Object.keys(req.body).map(reqKey => { if (reqKey === 'knowObject') { JSON.parse(req.body[reqKey]); } }

我确信有更好的结构可以使用,但我知道比询问 SO 使用哪种结构更清楚 ;)

谢谢大家!