如何在颤振中使用表单数据制作 http 帖子?
Posted
技术标签:
【中文标题】如何在颤振中使用表单数据制作 http 帖子?【英文标题】:How make a http post using form data in flutter? 【发布时间】:2020-01-10 18:15:04 【问题描述】:我正在尝试执行 http post 请求,我需要将正文指定为 form-data,因为服务器不会将请求视为原始请求。
这就是我正在做的:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatefulWidget
@override
_MyAppState createState() => _MyAppState();
class _MyAppState extends State<MyApp>
postTest() async
final uri = 'https://na57.salesforce.com/services/oauth2/token';
var requestBody =
'grant_type':'password',
'client_id':'3MVG9dZJodJWITSviqdj3EnW.LrZ81MbuGBqgIxxxdD6u7Mru2NOEs8bHFoFyNw_nVKPhlF2EzDbNYI0rphQL',
'client_secret':'42E131F37E4E05313646E1ED1D3788D76192EBECA7486D15BDDB8408B9726B42',
'username':'example@mail.com.us',
'password':'ABC1234563Af88jesKxPLVirJRW8wXvj3D'
;
http.Response response = await http.post(
uri,
body: json.encode(requestBody),
);
print(response.body);
@override
Widget build(BuildContext context)
return MaterialApp(
home: Container(
child: Center(
child: RaisedButton(
child: Text('Press Here'),
onPressed: ()
postTest();
,
),
),
),
);
这是实际的响应:
"error": "unsupported_grant_type",
"error_description": "grant type not supported"
这是预期的响应:
"access_token": "00D0b000000Bb08!AR8AQO.s8mAGXCbwV77FXNLQqc2vtl8g6_16miVbgWlQMsuNHsaf2IGLUwnMVXBOfAj19iznhqhwlPOi4tagvf7FFgiJJgoi",
"instance_url": "https://na57.salesforce.com",
"id": "https://login.salesforce.com/id/00D0b000000Bb08EAC/0050b000005nstiAAA",
"token_type": "Bearer",
"issued_at": "1567993324968",
"signature": "1+Zd/dSh9i7Moh2U0nFJLdXkVHqPlPVU6emwdYzXDPk="
您可以在 postman 在 raw(得到实际响应)和 form-data(得到预期响应)之间切换正文进行测试
PS:标头是客户端工具创建的临时标头。
【问题讨论】:
你找到相同的解决方案了吗?请分享 查看***.com/a/67559979/6314955 有什么解决办法吗?来自@MalithKuruwita 的上述链接也没有被接受的答案 @EightRice 如果您想将数据发送到接受内容类型的服务器:x-www-form-urlencoded,我提供的上述 URL 有效。它适用于文本数据。但是如果你想发送多部分/表单数据。像文件或图像到服务器(二进制数据),使用它(developerlibs.com/2020/07/…)。该博客还展示了如何发送文本数据。根据服务器接受的内容类型使用相关的 【参考方案1】:您也可以使用 MultiPartRequest,它肯定会工作
var request = new
http.MultipartRequest("POST",Uri.parse("$baseUrl/example/"));
request.headers.addAll(baseHeader);
request.fields['id'] = params.id.toString();
request.fields['regionId'] = params.regionId.toString();
request.fields['districtId'] = params.districtId.toString();
http.Response response = await http.Response.fromStream(await
request.send());
print('Uploaded! $response.body ++ $response.statusCode');
【讨论】:
【参考方案2】:此代码 sn-ps 成功执行 POST api 调用,该调用需要授权令牌和表单数据。
final headers = 'Authorization': 'Bearer $authToken';
var requestBody =
'shopId': '5',
'fromDate': '01/01/2021',
'toDate': '01/10/2022',
;
final response = await http.post(
Uri.parse(
'https://api.sample.com/mobile/dashboard/getdetails'),
headers: headers,
body: requestBody,
);
print("RESPONSE $response.body");
【讨论】:
【参考方案3】:HTTP 还不支持form-data
!
请改用DIO。它会自己处理一切!
【讨论】:
【参考方案4】:那么,您想将正文作为表单数据发送,对吗?也许你可以试试这个?对我来说这是工作
postTest() async
final uri = 'https://na57.salesforce.com/services/oauth2/token';
var requestBody =
'grant_type':'password',
'client_id':'3MVG9dZJodJWITSviqdj3EnW.LrZ81MbuGBqgIxxxdD6u7Mru2NOEs8bHFoFyNw_nVKPhlF2EzDbNYI0rphQL',
'client_secret':'42E131F37E4E05313646E1ED1D3788D76192EBECA7486D15BDDB8408B9726B42',
'username':'example@mail.com.us',
'password':'ABC1234563Af88jesKxPLVirJRW8wXvj3D'
;
http.Response response = await http.post(
uri,
body: requestBody,
);
print(response.body);
或者
postTest() async
final uri = 'https://na57.salesforce.com/services/oauth2/token';
http.Response response = await http.post(
uri, body:
'grant_type':'password',
'client_id':'3MVG9dZJodJWITSviqdj3EnW.LrZ81MbuGBqgIxxxdD6u7Mru2NOEs8bHFoFyNw_nVKPhlF2EzDbNYI0rphQL',
'client_secret':'42E131F37E4E05313646E1ED1D3788D76192EBECA7486D15BDDB8408B9726B42',
'username':'example@mail.com.us',
'password':'ABC1234563Af88jesKxPLVirJRW8wXvj3D'
);
print(response.body);
【讨论】:
【参考方案5】:使用 MultipartRequest 类
multipart/form-data 请求会自动将 Content-Type 标头设置为 multipart/form-data。
此值将覆盖用户设置的任何值。
参考 pub.dev 文档here
例如:
Map<String, String> requestBody = <String,String>
'field1':value1
;
Map<String, String> headers= <String,String>
'Authorization':'Basic $base64Encode(utf8.encode('user:password'))'
;
var uri = Uri.parse('http://localhost.com');
var request = http.MultipartRequest('POST', uri)
..headers.addAll(headers) //if u have headers, basic auth, token bearer... Else remove line
..fields.addAll(requestBody);
var response = await request.send();
final respStr = await response.stream.bytesToString();
return jsonDecode(respStr);
希望对你有帮助
【讨论】:
如果有人像我一样想知道,您可以使用await http.Response.fromStream(streamedResponse)
从流式响应中获取通常的响应对象【参考方案6】:
使用 POSTMAN 测试查询并获取格式非常有用。这允许您查看是否真的需要设置标头。请参阅下面的示例。我希望它有所帮助,而且不要太多
import 'dart:convert';
import 'package:http/http.dart';
class RegisterUser
String fullname;
String phonenumber;
String emailaddress;
String password;
Map data;
RegisterUser(this.fullname, this.phonenumber, this.emailaddress, this.password);
Future<void> registeruseraction() async
String url = 'https://api.url.com/';
Response response = await post(url, body:
'fullname' : fullname,
'phonenumber' : phonenumber,
'emailaddress' : emailaddress,
'password' : password
);
print(response.body);
data = jsonDecode(response.body);
【讨论】:
【参考方案7】:有一个dart包dio 它就像一个魅力,我用它作为标准来做 http 请求。 请阅读docs 也可以使用 dio 包发送表单数据
import 'package:dio/dio.dart';
postData(Map<String, dynamic> body)async
var dio = Dio();
try
FormData formData = new FormData.fromMap(body);
var response = await dio.post(url, data: formData);
return response.data;
catch (e)
print(e);
【讨论】:
在 Map 中没有参数时从哪里获取 url 那是一段代码。希望能得到想要的答案【参考方案8】:编辑 1(这适用于代码登录流程):
String url = "https://login.salesforce.com/services/oauth2/token";
http.post(url, body:
"grant_type": "authorization_code",
"client_id": "some_client_id",
"redirect_uri": "some_redirect_uri",
"code": "some_code_generated_by_salesforce_login",
"client_secret": "some_client_secret",
).then((response)
//--handle response
);
试一试“FormData”:
import 'package:dio/dio.dart';
FormData formData = new FormData.fromMap(dataMap);
retrofitClient.getToken(formData).then((response)//--handle respnse--);
'retrofitClient' 来自包 改造:^1.0.1+1
【讨论】:
无效的请求正文 \"Instance of 'FormData'\".【参考方案9】:改为使用 Map,因为 http 包中的 body 只有 3 种类型:String、List 或 Map。试试这个:
final uri = 'https://na57.salesforce.com/services/oauth2/token';
var map = new Map<String, dynamic>();
map['grant_type'] = 'password';
map['client_id'] = '3MVG9dZJodJWITSviqdj3EnW.LrZ81MbuGBqgIxxxdD6u7Mru2NOEs8bHFoFyNw_nVKPhlF2EzDbNYI0rphQL';
map['client_secret'] = '42E131F37E4E05313646E1ED1D3788D76192EBECA7486D15BDDB8408B9726B42';
map['username'] = 'example@mail.com.us';
map['password'] = 'ABC1234563Af88jesKxPLVirJRW8wXvj3D';
http.Response response = await http.post(
uri,
body: map,
);
【讨论】:
没用,post 方法仍然接受使用 json 对象 如果 body 是一个 Map,它被编码为使用编码的表单字段。请求的内容类型将设置为“application/x-www-form-urlencoded”。 pub.dev/documentation/http/latest/http/Client/post.html 似乎使用 Map 的行为更像是来自 HTML 表单的帖子,而不是官方 Flutter 文档中使用的 jsonEncode 方法。谢谢。修复了我的问题。 地图对我不起作用。我必须使用 Dio FormData,但我想知道为什么发送地图会收到 400 错误? @mohammad 你发了什么?【参考方案10】:你可以试试这个吗?
String url = 'https://myendpoint.com';
Map<String, String> headers =
"Content-Type": "application/x-www-form-urlencoded"
"Content-type": "application/json";
String json = '"grant_type":"password",
"username":"myuser@mail.com",
"password":"123456"';
// make POST request
Response response = await post(url, headers: headers, body: json);
// check the status code for the result
int statusCode = response.statusCode;
// this API passes back the id of the new item added to the body
String body = response.body;
【讨论】:
使用或不使用标题没有区别,我的意思是如何将正文作为表单数据发送 我也更新了我的问题,现在你可以测试更接近我真实情况的东西了。 @M.Massula 我认为在颤振中,没有任何选项可以请求使用表单数据。这是可能的,您可以使用 json 传递数据。 这在标题字符串之间缺少逗号。以上是关于如何在颤振中使用表单数据制作 http 帖子?的主要内容,如果未能解决你的问题,请参考以下文章