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

Flutter http MultipartRequest中文字段无法被Gin服务器接收求助

Flutter MultipartRequest 提交中文字段到Gin服务器为null的问题解决

我之前也碰到过类似的跨端表单编码问题,结合你的代码和请求头对比来看,问题核心在于Flutter的MultipartRequest与Gin框架对非ASCII字符的编码/解析逻辑不匹配——Postman能正常提交说明Gin本身支持中文解析,问题出在Flutter请求的构造环节。下面给出几个经过验证的解决方案:

方案一:在Gin端手动解析MultipartForm

Gin的PostForm方法默认依赖ParseForm,但multipart类型的表单需要显式调用ParseMultipartForm才能正确解析所有字段(包括中文)。修改你的Gin处理代码:

import (
    "log"
    "net/http"
    "strconv"

    "github.com/gin-gonic/gin"
)

func HandleUserRegister(context *gin.Context) {
    // 先显式解析multipart表单,设置足够的内存限制(这里设为10MB)
    err := context.Request.ParseMultipartForm(10 << 20)
    if err != nil {
        log.Errorf("解析表单失败: %v", err)
        context.JSON(http.StatusBadRequest, gin.H{"error": "表单解析错误"})
        return
    }

    // 从MultipartForm中直接取值
    userAcc := context.Request.MultipartForm.Value["user_acc"][0]
    userNickName := context.Request.MultipartForm.Value["user_nick_name"][0]
    userPassword := context.Request.MultipartForm.Value["user_password"][0]
    userType := context.Request.MultipartForm.Value["user_type"][0]
    userTypeInt, _ := strconv.Atoi(userType)

    log.Infof("userAcc: %s, userNickName: %s, userPassword: %s", userAcc, userNickName, userPassword)
    // 其他字段处理逻辑...
}

方案二:在Flutter端对中文字段做URL编码

如果不想修改Gin端代码,可以在Flutter侧将中文字段进行URL编码,Gin端接收后再解码还原:

Flutter代码修改:

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

// ...

var request = new http.MultipartRequest("POST", _uri);
request.fields['user_acc'] = _userAcc;
// 对中文昵称进行URL编码
request.fields['user_nick_name'] = Uri.encodeComponent('中文名字');
request.fields['user_password'] = _password;

// 发送请求...

Gin代码修改:

import (
    "log"
    "net/url"
    "strconv"

    "github.com/gin-gonic/gin"
)

func HandleUserRegister(context *gin.Context) {
    userAcc := context.PostForm("user_acc")
    // 解码URL编码的中文字段
    userNickNameRaw := context.PostForm("user_nick_name")
    userNickName, err := url.QueryUnescape(userNickNameRaw)
    if err != nil {
        log.Errorf("解码昵称失败: %v", err)
        userNickName = "" // 设置默认值或返回错误
    }
    userPassword := context.PostForm("user_password")

    log.Infof("userAcc: %s, userNickName: %s, userPassword: %s", userAcc, userNickName, userPassword)
    // 其他字段处理逻辑...
}

方案三:升级Flutter的http库到最新版本

旧版本的Dart http库可能存在multipart字段编码的bug,升级到最新版大概率能解决问题。修改pubspec.yaml中的依赖:

dependencies:
  http: ^1.1.0 # 替换为最新版本号

执行flutter pub get后重新运行项目即可。

方案四:手动构建Multipart请求体(兜底方案)

如果以上方法都无效,可以完全手动控制请求体的编码,确保中文以UTF-8格式传输:

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

// ...

// 生成唯一边界符
var boundary = 'dart-custom-boundary-${DateTime.now().millisecondsSinceEpoch}';
var bodyBuffer = StringBuffer();

// 添加各个字段
bodyBuffer.write('--$boundary\r\n');
bodyBuffer.write('Content-Disposition: form-data; name="user_acc"\r\n\r\n');
bodyBuffer.write(_userAcc);
bodyBuffer.write('\r\n');

bodyBuffer.write('--$boundary\r\n');
bodyBuffer.write('Content-Disposition: form-data; name="user_nick_name"\r\n');
bodyBuffer.write('Content-Type: text/plain; charset=utf-8\r\n\r\n');
bodyBuffer.write('中文名字');
bodyBuffer.write('\r\n');

bodyBuffer.write('--$boundary\r\n');
bodyBuffer.write('Content-Disposition: form-data; name="user_password"\r\n\r\n');
bodyBuffer.write(_password);
bodyBuffer.write('\r\n');

// 结束边界
bodyBuffer.write('--$boundary--\r\n');

// 转换为UTF-8编码的字节流
Uint8List bodyBytes = utf8.encode(bodyBuffer.toString());

// 构建请求
var request = http.Request('POST', _uri);
request.headers['Content-Type'] = 'multipart/form-data; boundary=$boundary';
request.bodyBytes = bodyBytes;

// 发送请求并处理响应
var response = await request.send();
if (response.statusCode == 200) {
    // 处理成功响应
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:05:50