通过后台获取到policy信息之后进行文件上传,结果使用http库一直提示400
使用postman或者apifox都可以上传成功
Future<String?> uplaodFile({required File file}) async {
// 获取policy信息
final ossPolicy = await getOSSPolicy(filename: path.basename(file.path));
if (ossPolicy == null) {
return null;
}
// Content-type
final type = mime(path.basename(file.path))?.split("/").first;
final subtype = mime(path.basename(file.path))?.split("/").last;
// Form-data
var request =
http.MultipartRequest("POST", Uri.parse(ossPolicy.host ?? ossUrl))
..fields["OSSAccessKeyId"] = ossPolicy.accessKeyId ?? ""
..fields["Signature"] = ossPolicy.signature ?? ""
..fields["policy"] = ossPolicy.policy ?? ""
..fields["key"] = ossPolicy.fileId.toKey()
..fields["success_action_status"] = "200"
..files.add(await http.MultipartFile.fromPath('file', file.path,
contentType: MediaType(type ?? "text", subtype ?? "plain")));
final response = await request.send();
if (response.statusCode != 200) {
logger.e(await response.stream.bytesToString());
return null;
}
return ossPolicy.fileId;
}
请求返回结果:
I/flutter (13104): │ ⛔ <?xml version="1.0" encoding="UTF-8"?>
I/flutter (13104): │ ⛔ <Error>
I/flutter (13104): │ ⛔ <Code>MalformedPOSTRequest</Code>
I/flutter (13104): │ ⛔ <Message>The body of your POST request is not well-formed multipart/form-data</Message>
I/flutter (13104): │ ⛔ <RequestId>65C0AFBC84CC8A3733DFF7C4</RequestId>
I/flutter (13104): │ ⛔ <HostId>oss.*****.com</HostId>
I/flutter (13104): │ ⛔ <EC>0006-00000109</EC>
I/flutter (13104): │ ⛔ <RecommendDoc>https://api.aliyun.com/troubleshoot?q=0006-00000109</RecommendDoc>
I/flutter (13104): │ ⛔ </Error>
I/flutter (13104): │ ⛔
网上查看说是PostObject请求中表单域格式不正确
那这该如何修改???
根据错误信息The body of your POST request is not well-formed multipart/form-data
,问题可能出在MultipartFormData的构造上。确保您正确设置了所有必需的表单字段和文件,并且格式符合OSS服务的要求。
您可以尝试以下修改后的代码:
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:mime_type/mime_type.dart';
Future<String?> uploadFile({required File file}) async {
// 获取policy信息
final ossPolicy = await getOSSPolicy(filename: path.basename(file.path));
if (ossPolicy == null) {
return null;
}
// Content-type
final type = mime(path.basename(file.path))?.type;
// Form-data
var request = http.MultipartRequest("POST", Uri.parse(ossPolicy.host ?? ossUrl))
..headers.addAll({
'Content-Type': 'multipart/form-data',
})
..fields.addAll({
'OSSAccessKeyId': ossPolicy.accessKeyId ?? '',
'Signature': ossPolicy.signature ?? '',
'policy': base64Encode(utf8.encode(ossPolicy.policy ?? '')),
'key': ossPolicy.fileId.toKey(),
'success_action_status': '200',
})
..files.add(await http.MultipartFile.fromPath(
'file',
file.path,
contentType: MediaType(type),
));
final response = await request.send();
if (response.statusCode != 200) {
logger.e(await response.stream.bytesToString());
return null;
}
return ossPolicy.fileId;
}
这里做了一些调整:
policy
字段值转换为Base64编码,因为有时候policy可能包含特殊字符,需要进行URL安全的Base64编码。Content-Type
头,虽然http库会自动处理这个,但有时明确设置可能会解决问题。contentType
属性直接使用mime
库获取到的类型。请检查并确认您的getOSSPolicy
函数返回的policy是否需要Base64编码,如果不需要,请恢复原样。同时,请确保其他字段(如accessKeyId、signature等)的格式与后端要求一致。
阿里云oss明确要求form请求开头必须是以Content-Disposition: form-data; name="*"开头,而在上传文件的时候,http库在添加_headerForFile方法的时候,将Content-Type: ${file.contentType}放在了Content-Disposition之前,所以导致oss认为请求格式不正确,修改他们的位置顺序之后请求就回复正常了。
修改之前:
/// Returns the header string for a file.
///
/// The return value is guaranteed to contain only ASCII characters.
String _headerForFile(MultipartFile file) {
var header = 'Content-Type: ${file.contentType}\r\n'
'Content-Disposition: form-data; name="${_browserEncode(file.field)}"';
if (file.filename != null) {
header = '$header; filename="${_browserEncode(file.filename!)}"';
}
return '$header\r\n\r\n';
}
修改之后:
/// Returns the header string for a file.
///
/// The return value is guaranteed to contain only ASCII characters.
String _headerForFile(MultipartFile file) {
var header =
'Content-Disposition: form-data; name="${_browserEncode(file.field)}"\r\n'
'Content-Type: ${file.contentType}';
if (file.filename != null) {
header = '$header; filename="${_browserEncode(file.filename!)}"';
}
return '$header\r\n\r\n';
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
对象存储 OSS 是一款安全、稳定、高性价比、高性能的云存储服务,可以帮助各行业的客户在互联网应用、大数据分析、机器学习、数据归档等各种使用场景存储任意数量的数据,以及进行任意位置的访问,同时通过丰富的数据处理能力更便捷地使用数据。