You need to enable JavaScript to run this app. Flutter中如何发送携带JSON对象、图片的multipart/form-data POST请求
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何发送携带JSON对象、图片的multipart/form-data POST请求

Dart 环境下携带嵌套JSON对象+图片的multipart POST实现

关键前置修正

注意:你原配置里有个会直接导致请求失败的问题:不要手动在请求头里声明Content-Type: multipart/form-data。
multipart/form-data 格式要求每个请求分段之间携带随机生成的boundary边界标识,手动写死的Content-Type会缺失这个标识,服务端会直接无法解析请求结构。这个头必须由网络客户端在构建请求体时自动生成,你只需要在请求头里保留自定义的认证和租户参数即可,修正后的请求头配置:

final Map<String, String> headers = {
  'tenantId': tenantId,
  'x-access-token': token,
};

核心实现逻辑

由于multipart/form-data 原生只支持扁平键值对格式,无法直接承载你定义的嵌套结构化对象,标准处理方案是:

  • 把整个嵌套的业务数据(也就是你写的包含Id、嵌套Details结构的对象)序列化成合法JSON字符串,作为普通表单字段提交
  • 把图片封装成二进制文件表单字段,和JSON数据字段一起放到multipart请求体里

先准备序列化的业务数据:

import 'dart:convert';

// 构建你的业务数据对象
final businessPayload = {
  "Id": Id,
  "Details": {
    "name": Name,
    "centroid": centroid,
    "attribute": {
      "boundaryOpacity": boundaryOpacity,
      "boundaryWeight": boundaryWeight,
      "boundaryColor": boundaryColor,
      "labelColor": labelColor,
    },
  }
};
// 序列化为JSON字符串
final businessPayloadJson = jsonEncode(businessPayload);

方案1:使用官方http包实现

import 'package:http/http.dart' as http;

// 初始化multipart POST请求
final request = http.MultipartRequest(
  'POST',
  Uri.parse('你的目标接口地址'),
);

// 注入自定义请求头
request.headers.addAll(headers);

// 传入序列化后的JSON业务数据,字段名和后端约定保持一致
request.fields['payload'] = businessPayloadJson;

// 传入图片字段,支持两种常见来源:
// 1. 本地文件路径来源
request.files.add(
  await http.MultipartFile.fromPath(
    'image', // 字段名和后端接口的图片参数名保持一致
    '本地图片的绝对文件路径',
  )
);

// 2. 内存字节流来源(比如从图片选择器拿到的Uint8List数据)
// request.files.add(
//   http.MultipartFile.fromBytes(
//     'image',
//     capturedImageBytes,
//     filename: 'upload_target.jpg',
//     contentType: MediaType('image', 'jpeg'),
//   )
// );

// 发送请求并获取响应
final response = await request.send();
final responseContent = await response.stream.bytesToString();

方案2:使用dio网络库实现

import 'package:dio/dio.dart';

final dioClient = Dio();
// 构建multipart表单数据
final formData = FormData.fromMap({
  // 序列化的业务JSON数据
  'payload': businessPayloadJson,
  // 本地文件图片字段
  'image': await MultipartFile.fromFile(
    '本地图片的绝对文件路径',
    filename: 'upload_target.jpg',
  ),
  // 内存字节流图片替换写法
  // 'image': MultipartFile.fromBytes(
  //   capturedImageBytes,
  //   filename: 'upload_target.jpg',
  //   contentType: MediaType('image', 'jpeg'),
  // ),
});

final response = await dioClient.post(
  '你的目标接口地址',
  data: formData,
  options: Options(
    headers: headers,
    // 不要手动设置Content-Type,dio会自动生成带boundary的multipart头
  ),
);

常见踩坑说明

  • 字段名对齐:所有表单字段(不管是序列化JSON的字段名、还是图片的字段名)都要和后端接口的参数定义完全一致,否则后端无法解析拿到对应值
  • 禁止未序列化直接传嵌套对象:如果直接把嵌套Dart对象放到multipart的fields里,客户端只会把对象转成无意义的{...}字符串,服务端无法解析成合法JSON,必须主动调用jsonEncode做序列化
  • 不要强制覆盖Content-Type:手动写死的multipart Content-Type会缺失boundary标识,是最高发的请求解析失败原因

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.10 06:36:01