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

如何在TypeScript中模拟含嵌套文件的form-data列表?

解决TypeScript中嵌套数组内文件提交后返回null的问题

问题根源

直接提交JSON对象时,二进制buffer无法被正确序列化,且嵌套数组的文件字段不符合multipart/form-data的解析规则,导致后端无法识别,最终返回null。

解决方案

改用FormData构造表单数据,手动处理嵌套数组的字段命名格式,确保后端能正确解析数组结构和文件内容。

前端提交代码示例

import fs from 'fs';
import path from 'path';
import fetch from 'node-fetch'; // 根据项目实际使用的HTTP客户端调整

const fruitImage = fs.readFileSync(path.resolve(__dirname, './fruit-image.png'));

export const submitFruitForm = async () => {
  const formData = new FormData();

  // 根层级字段
  formData.append('id', 'some id');
  // 根层级文件:将buffer转为Blob并附带文件名
  formData.append('fruit_image', new Blob([fruitImage]), 'fruit-image.png');

  // 处理嵌套数组的水果项
  const fruits = [
    {
      id: 'banana',
      fruit_image: { name: 'fruit-image.png', buffer: fruitImage }
    }
  ];

  fruits.forEach((fruit, index) => {
    // 数组元素的普通字段,使用索引式命名:fruits[0][id]
    formData.append(`fruits[${index}][id]`, fruit.id);
    // 数组元素的文件字段,同样使用索引式命名
    formData.append(
      `fruits[${index}][fruit_image]`,
      new Blob([fruit.fruit_image.buffer]),
      fruit.fruit_image.name
    );
  });

  // 发送请求
  const response = await fetch('你的接口地址', {
    method: 'POST',
    body: formData
    // 无需手动设置Content-Type,客户端会自动添加带boundary的正确请求头
  });

  const result = await response.json();
  console.log('提交结果:', result);
};

后端解析注意事项

以NestJS为例,需要使用AnyFilesInterceptor捕获所有文件,再手动匹配嵌套数组的对应字段:

import { Controller, Post, UseInterceptors, UploadedFiles, Body } from '@nestjs/common';
import { AnyFilesInterceptor } from '@nestjs/platform-express';

@Controller('fruits')
export class FruitsController {
  @Post()
  @UseInterceptors(AnyFilesInterceptor())
  async submitForm(
    @UploadedFiles() files: Express.Multer.File[],
    @Body() body: Record<string, string>
  ) {
    // 解析body中的fruits数组(前端提交时会被转为字符串格式)
    const fruits = JSON.parse(body.fruits).map((fruit: any, index: number) => {
      // 根据字段名匹配对应文件
      const matchedFile = files.find(f => f.fieldname === `fruits[${index}][fruit_image]`);
      return {
        ...fruit,
        fruit_image: matchedFile // 将文件对象或其buffer赋值给对应字段
      };
    });

    // 匹配根层级文件
    const rootFruitImage = files.find(f => f.fieldname === 'fruit_image');

    return {
      id: body.id,
      fruit_image: rootFruitImage,
      fruits
    };
  }
}

关键要点

  • 避免直接提交JSON:二进制buffer在JSON序列化时会丢失文件特性,必须使用multipart/form-data格式提交。
  • 索引式字段命名:嵌套数组的字段必须用fruits[索引][字段名]的格式,后端解析器才能正确识别数组结构。
  • 不要手动设置Content-Type:客户端会自动生成带boundary的multipart/form-data请求头,手动设置会导致解析失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 08:00:24