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

Flutter使用Dio发送Multipart请求报错:后端缺失complaintData

问题排查与修复方案

核心问题分析

后端抛出MissingServletRequestPartException: Required part 'complaintData' is not present,主要有两个原因:

  • 字段名拼写错误:FormData中"images:"多了一个冒号,干扰了Multipart请求的字段解析逻辑,导致后端无法正确识别所有请求部分。
  • JSON数据未序列化:直接将Map类型的complaintData放入FormData,Spring Boot无法自动解析这种嵌套结构,需要先将Map转为JSON字符串。

修复后的代码

import 'dart:convert'; // 需导入json编码工具

Future<int> saveComplaint({
    required String complaintSubject,
    required String complaintDescription,
    required String complaintPriority,
    required String categoryToken,
    required int pinCode,
    required String address,
    required String wardNo,
    required int contactNo,
  }) async {
    try {
      String? accessToken = await _secureStorage.readAccessToken();
      String? userToken = await _secureStorage.readUserToken();
      Options options = Options(
        validateStatus: (_) => true,
        contentType: Headers.multipartFormDataContentType,
        responseType: ResponseType.json,
        headers: {HttpHeaders.authorizationHeader: bearerPrefix + accessToken!},
      );

      List<dio.MultipartFile> files=[];
      for (int i = 0; i < images.length; i++) {
        XFile image = images[i];
        files.add(await dio.MultipartFile.fromFile(
          image.path,
          filename: 'image_$i.jpg',
        ));
      }

      Map<String, dynamic> complaintData = {
        'complaintSubject': complaintSubject,
        'complaintDescription': complaintDescription,
        'complaintPriority': complaintPriority,
        'categoryToken': categoryToken,
        'pincode': pinCode.toString(),
        'address': address,
        'wardNo': wardNo,
        'contactNo': contactNo.toString(),
        'userToken': userToken ?? '',
      };

      // 1. 将complaintData序列化为JSON字符串
      String complaintJson = jsonEncode(complaintData);
      // 2. 修正images字段名的冒号问题
      dio.FormData formData=dio.FormData.fromMap({
        "complaintData": complaintJson,
        "images": files
      });

      dio.Response response = await _dio.post(saveComplaintUrl, data: formData,options: options);
      log('Response data: ${response.data}');
      Map<String, dynamic> responseData = response.data;
      if(responseData.isNotEmpty){
        return responseData['code'];
      }
    } catch (err) {
      log('$err');
      debugPrintStack();
    }
    return -1;
  }

额外注意事项

  • 确保Spring Boot后端接口中,complaintData参数类型为String,接收后再反序列化为对应实体类。
  • 若后端期望直接接收实体类类型的complaintData,也可以尝试将Map拆分为FormData的平级字段,但JSON字符串的方式兼容性更强,更贴近Postman的请求格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:10:07