如何在flutter中使用url编码的主体发出HTTP POST请求?

时间:2018-04-12 13:14:02

标签: dart flutter

我正在尝试使用内容类型作为网址编码来发布帖子请求。当我写body : json.encode(data)时,它编码为纯文本。

如果我写body: data,我会收到错误type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String' in type cast

这是数据对象

var match = {
  "homeTeam": {"team": "Team A"},
  "awayTeam": {"team": "Team B"}
};

我的要求

var response = await post(Uri.parse(url),
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: match,
    encoding: Encoding.getByName("utf-8"));

10 个答案:

答案 0 :(得分:14)

您需要添加三个额外步骤: 首先,您需要将json映射转换为String(使用json.encode) 然后,如果要将其作为application / x-www-form-urlencoded发送,则需要对其进行Uri编码。 最后,您需要提供要发布名称的参数。

例如(注意,这是使用dart:io HttpClient,但它基本相同):

  Future<HttpClientResponse> foo() async {
    Map<String, dynamic> jsonMap = {
      'homeTeam': {'team': 'Team A'},
      'awayTeam': {'team': 'Team B'},
    };
    String jsonString = json.encode(jsonMap); // encode map to json
    String paramName = 'param'; // give the post param a name
    String formBody = paramName + '=' + Uri.encodeQueryComponent(jsonString);
    List<int> bodyBytes = utf8.encode(formBody); // utf8 encode
    HttpClientRequest request =
        await _httpClient.post(_host, _port, '/a/b/c');
    // it's polite to send the body length to the server
    request.headers.set('Content-Length', bodyBytes.length.toString());
    // todo add other headers here
    request.add(bodyBytes);
    return await request.close();
  }

以上是针对dart:io版本(当然,你可以在Flutter中使用) 如果您想坚持使用该软件包:http版本,那么您需要稍微调整一下Map。 body必须是Map&lt; String,String&gt;。您需要确定您想要的POST参数。你想要两个:homeTeam和awayTeam?或者一个,比如,teamJson?

此代码

  Map<String, String> body = {
    'name': 'doodle',
    'color': 'blue',
    'homeTeam': json.encode(
      {'team': 'Team A'},
    ),
    'awayTeam': json.encode(
      {'team': 'Team B'},
    ),
  };

  Response r = await post(
    url,
    body: body,
  );

在线上产生

  

名=涂鸦&安培;颜色=蓝色&安培; homeTeam =%7B%22team%22%3A%22Team + A%22%7D&安培; awayTeam =%7B%22team%22%3A%22Team + B%22%7D

或者,这个

  Map<String, String> body = {
    'name': 'doodle',
    'color': 'blue',
    'teamJson': json.encode({
      'homeTeam': {'team': 'Team A'},
      'awayTeam': {'team': 'Team B'},
    }),
  };

  Response r = await post(
    url,
    body: body,
  );

在线上产生

  

名=涂鸦&安培;颜色=蓝色&安培; teamJson =%7B%22homeTeam%22%3A%7B%22team%22%3A%22Team + A%22%7D%2C%22awayTeam%22%3A%7B%22team% 22%3A%22Team + B%22%7D%7D

包:http客户端负责:编码Uri.encodeQueryComponent,utf8编码(请注意,这是默认值,因此无需指定)并在Content-Length标头中发送长度。您仍然必须执行json编码。

答案 1 :(得分:10)

我想向您推荐dio包,dio是Dart / Flutter的强大Http客户端,它支持拦截器,FormData,请求取消,文件下载,超时等。

dio非常易于使用,在您的情况下,您可以:

Map<String, String> body = {
'name': 'doodle',
'color': 'blue',
'teamJson': {
  'homeTeam': {'team': 'Team A'},
  'awayTeam': {'team': 'Team B'},
  },
};

dio.post("/info",data:body, options: 
  new Options(contentType:ContentType.parse("application/x-www-form-urlencoded")))    

dio可以自动编码数据。

更多详情请参阅dio

答案 2 :(得分:5)

您需要使用json.encode

示例;

var match = {
  "homeTeam": {"team": "Team A"},
  "awayTeam": {"team": "Team B"}
};
var response = await post(Uri.parse(url),
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: json.encode(match),
    encoding: Encoding.getByName("utf-8"));

答案 3 :(得分:1)

我建议使用Dio库。使用API​​可以提供很多支持。

具有最新的Dio版本。只需执行以下操作:

BaseOptions options = new BaseOptions(
baseUrl: "https://www.xx.com/api",
connectTimeout: 5000,
receiveTimeout: 3000,);
Dio dio = new Dio(options);
//
Map<String, String> params = Map();
params['username'] = '6388';
params['password'] = '123456';
//
response = await dio.post("/login", data: FormData.fromMap(params));

答案 4 :(得分:0)

我来到这里只是想发出HTTP POST请求。这是如何执行此操作的示例:

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


makePostRequest() async {

  final uri = 'http://httpbin.org/post';
  final headers = {'Content-Type': 'application/json'};
  Map<String, dynamic> body = {'id': 21, 'name': 'bob'};
  String jsonBody = json.encode(body);
  final encoding = Encoding.getByName('utf-8');

  Response response = await post(
    uri,
    headers: headers,
    body: jsonBody,
    encoding: encoding,
  );

  int statusCode = response.statusCode;
  String responseBody = response.body;
}

答案 5 :(得分:0)

下面的代码是我创建的用于发送POST请求的功能

Future<http.Response> postData(String url, Map<String, dynamic> data) async {
Map<String, String> headers = await _getHeaders();

http.Response response = await http.post(
  Uri.parse(kBaseUrl + url),
  headers: headers,
  body: data,
  encoding: Encoding.getByName('utf-8'),
);

return response;
}

下面的代码是一个示例用法

Map<String, dynamic> authData = {
    "email": "testsdsd",
    "password": "sdsdsd",
  };

  // send an auth request to the API
  http.Response response = await _networkService.postData(
    'authenticate',
    authData,
  );

答案 6 :(得分:0)

我是用dart的http包做到这一点的。不太花哨。我的端点没有用其他方法接受参数,但是像这样接受了它们,并在参数中包含了括号。

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

String url = "<URL>";

Map<String, String> match = {
  "homeTeam[team]": "Team A",
  "awayTeam[team]": "Team B",
};

Map<String, String> headers = {
    "Content-Type": "application/x-www-form-urlencoded"
}

http.post(url, body: body, headers: headers).then((response){
    print(response.toString());
});

答案 7 :(得分:0)

Map<String, String> body = {
  'getDetails': 'true'
};

final response = await 
http.post("https://example.com/", body: body);

if (response.statusCode == 200) {
//Your code
}

答案 8 :(得分:0)

在“ UserModel”位置输入模型名称,并且不要在主体中传递String,这将使用“ Map”产生问题,如下所示。

static Future<UserModel> performUserLogin(String username, String password) async{
    
        try{
    
          Map<String, String> headers = {"Content-type": "application/json"};
          
    
          Map<String, String> JsonBody = {
            'username':  username,
            'password': password
          };
    
          print("The JSON Object is here $body");
          // make POST request
          final response = await http.post(loginAPIURL,body: JsonBody);
          // check the status code for the result
          int statusCode = response.statusCode;
          print("Login calling $response");
    
    
          if (statusCode == 200){
    
          
    
          }else{
            return null;
            //return UserModel();
            throw Exception("Error in login");
          }
    
        } catch (e) {
          throw Exception(e);
        }
      }

答案 9 :(得分:0)

使用 DIO 的简单获取请求:

    Future<dynamic> get(String uri, {
    Map<String, dynamic> queryParameters,
    Options options,
  }) async {
    try {
      var response = await _dio.get(
        uri,
        queryParameters: queryParameters,
        options: options,
      );
      return response.data;
    } on SocketException catch (e) {
      throw SocketException(e.toString());
    } on FormatException catch (_) {
      throw FormatException("Unable to process the data");
    } catch (e) {
      throw e;
    }
  }

使用 DIO 的简单发布请求{您也可以发送文件和图像}:

Future<dynamic> post(
    String uri, {
    data,
    Map<String, dynamic> queryParameters,
    Options options,
  }) async {
    try {
      var response = await _dio.post(
        uri,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );
      return response.data;
    } on FormatException catch (_) {
      throw FormatException("Unable to process the data");
    } catch (e) {
      throw e;
    }
  }