You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular提交FormData上传文件到Node.js接口时req.body为空的解决方法

Angular提交FormData上传文件时Node.js端req.body为空的解决方案

问题描述

我正从Angular向Node.js端点POST两个字段。
平时我直接在请求体中提交参数,Node端可以正常获取,但这次我需要提交表单来上传文件。
以下是我最初Angular端提交FormData的代码:

var APIURL = sessionStorage.getItem('endPoint') + "profile/updateeocoverage"; 
let formData = new FormData();
formData.append("data", JSON.stringify(this.payLoad));
if (this.eofile) {
  formData.append("myfile", this.eofile, this.eofile.name);
}
this.httpClient.post(APIURL,  formData).subscribe(
  result => {
  // 后续逻辑
  ....

我的问题是Node端按如下方式获取请求体时,返回的req.body是空对象{}:

router.post('/updateeocoverage', async   (req, res, next) => {
    console.log(req.body)
    return;
    // 后续逻辑
    ....

解决方法

使用Multer可以解决该问题,不过需要做额外配置来指定文件名,同时还需要实现用户鉴权,避免接口被恶意调用,具体实现如下:

1. 引入依赖

const multer = require('multer')
const path = require('path')

2. 实现用户鉴权逻辑

为了实现用户鉴权,我把鉴权参数放在请求头中传递,测试下来通过formdata.append的方式传参无法被鉴权逻辑正常读取。鉴权逻辑会返回是否允许上传,防止未授权用户调用接口上传文件:

async function authenticateUser(req, file, cb) {
    let tempcred = JSON.parse(req.headers.data)
    let credentials = tempcred.credentials;
    let userData = await utils.isValidUser((credentials), false);
    if (userData.isValid == false) {
        cb(null, false)
        return;
    }
    else {
        cb(null, true)
    }
}

3. 配置Multer存储规则

由于Multer默认会给上传的文件生成随机文件名,而我需要用用户ID加原文件扩展名来保存文件,因此做了如下配置:

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'uploads/eofiles/')
    },
    filename: async function (req, file, cb) {
        let tempcred = JSON.parse(req.headers.data)
        let credentials = tempcred.credentials;
        let userid = await utils.decrypt(credentials.userid, process.env.SECRET);
        cb(null, userid + path.extname(file.originalname))
    }
});

4. 初始化Multer实例

var upload = multer({ storage: storage, fileFilter: authenticateUser })

5. 调整路由配置

注意upload.single("myfile")中的参数myfile对应前端FormData里文件字段的键名:

router.post('/updateeofile', upload.single("myfile"), async (req, res, next) => {
let filename = req.file.filename // 获取保存的文件名
...
// 后续业务逻辑,比如将文件信息存入数据库等
...
});

6. 调整Angular端上传代码

var APIURL = sessionStorage.getItem('endPoint') + "eoset/updateeofile";    
    const httpOptions = {
      headers: new HttpHeaders({
        'data': `${JSON.stringify(this.payLoad)}`
      })
 };
 let formData = new FormData();
    if (this.eofile) {
      formData.append("myfile", this.eofile, this.eofile.name);
    }
    this.httpClient.post(APIURL, formData, httpOptions).subscribe(
      result => {
        // 成功回调逻辑
...
 },
      error => {
        // 错误处理逻辑
});

我今天在这个问题上花了6个小时,希望这篇内容能帮你节省时间。


内容的提问来源于stack exchange,提问作者Danielle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 13:54:03