Flutter中如何获取含文件的MultipartRequest原始字符串?
解决方案
1. 问题根源
Multipart请求的请求体包含二进制文件内容,并非纯UTF-8编码文本,直接用utf.decode()转换必然触发FormatException。正确思路是直接用二进制数据参与签名计算,而非强行转成字符串。
2. 针对MultipartRequest的处理步骤
步骤1:构造请求并获取二进制请求体
import 'package:http/http.dart' as http; // 构造Multipart请求 var request = http.MultipartRequest('POST', Uri.parse('你的API地址')); // 添加文本字段 request.fields['username'] = 'test_user'; // 添加文件 request.files.add(await http.MultipartFile.fromPath('avatar', '/path/to/avatar.jpg')); // 获取完整二进制请求体 List<int> requestBodyBytes = await request.finalize().toBytes();
步骤2:生成签名
按照API规范拼接负载前缀,再与请求体二进制合并后计算HMAC-SHA256:
import 'dart:convert'; import 'package:crypto/crypto.dart'; // 按规范提取各字段 String path = '/user/avatar'; // 主机/api之后的路径,不含查询参数 String verb = 'POST'; String token = 'Bearer xxxxxx'; String timestamp = DateTime.utc.now().toIso8601String(); // 确保是UTC+0的ISO8601格式 // 构造签名前缀字节 String prefixStr = 'path=$path&verb=$verb&token=$token×tamp=$timestamp&body='; List<int> prefixBytes = utf8.encode(prefixStr); // 合并前缀与请求体二进制 List<int> signaturePayload = [...prefixBytes, ...requestBodyBytes]; // 计算HMAC-SHA256并base64编码 String secretKey = '你的密钥'; Hmac hmac = Hmac(sha256, utf8.encode(secretKey)); Digest digest = hmac.convert(signaturePayload); String signature = base64.encode(digest.bytes);
3. 针对Dio FormData的处理步骤
步骤1:构造FormData并获取二进制请求体
import 'package:dio/dio.dart'; // 构造FormData var formData = FormData.fromMap({ 'username': 'test_user', 'avatar': await MultipartFile.fromFile('/path/to/avatar.jpg'), }); // 获取二进制请求体 List<int> requestBodyBytes = await formData.finalize();
步骤2:生成签名
和MultipartRequest的签名生成逻辑完全一致,用前缀字节拼接请求体二进制后计算签名即可。
4. 特殊情况确认
如果上述方法不符合API要求,需确认:
- API是否仅要求签名包含文本字段,而非整个Multipart请求体?若是,单独提取文本字段拼接成指定格式字符串即可。
- API是否要求对Multipart请求体先做base64编码,再加入签名负载?若是,先将请求体二进制转base64字符串,再拼接到前缀中。
内容的提问来源于stack exchange,提问作者Dias Utsman
相关产品推荐
相关产品推荐

