Flutter:HttpClient发布contentLength-异常 [英] Flutter: HttpClient post contentLength -- exception

查看:382
本文介绍了Flutter:HttpClient发布contentLength-异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很奇怪...

为了将一些JSON数据发布到我的服务器,我将contentLength定义为JSON编码数据的长度,但是随后我收到一个异常,内容为"内容大小超出了指定的contentLength ".差异是1个字节.

In order to post some JSON data to my server, I define the contentLength to the length of the JSON encoded data but I then receive an exception that says "Content size exceeds specified contentLength". Difference is 1 byte.

这是源代码:

Future<Map> ajaxPost(String serviceName, Map data) async {
  var responseBody = json.decode('{"data": "", "status": "NOK"}');
  try {
    var httpClient = new HttpClient();
    var uri = mid.serverHttps ? new Uri.https(mid.serverUrl, _serverApi + serviceName)
                              : new Uri.http(mid.serverUrl, _serverApi + serviceName);
    var request = await httpClient.postUrl(uri);
    var body = json.encode(data);

    request.headers
      ..add('X-mobile-uuid', await _getDeviceIdentity())
      ..add('X-mobile-token', await mid.getMobileToken());

    request.headers.contentLength = body.length;
    request.headers.set('Content-Type', 'application/json; charset=utf-8');
    request.write(body);

    var response = await request.close();
    if (response.statusCode == 200){
      responseBody = json.decode(await response.transform(utf8.decoder).join());

      //
      // If we receive a new token, let's save it
      //
      if (responseBody["status"] == "TOKEN"){
        await mid.setMobileToken(responseBody["data"]);

        // Let's change the status to "OK", to make it easier to handle
        responseBody["status"] = "OK";
      }
    }
  } catch(e){
    // An error was received
    throw new Exception("AJAX ERROR");
  }
  return responseBody;
}

在其他时候,它工作正常...

Some other times, it works fine...

我对这段代码有什么错吗?

Am I doing anything wrong with this code?

非常感谢您的帮助.

使用解决方案进行编辑:

非常感谢您的帮助.使用 utf8.encode(json.encode(data))的简单事实不能完全起作用.因此,我转向了 http 库,它现在就像一个魅力一样工作.代码更轻巧!

Many thanks for your help. The simply fact of using utf8.encode(json.encode(data)) did not fully work. So, I turned to the http library and it now works like a charm. The code is even lighter!

这是该代码的新版本:

Future<Map> ajaxPut(String serviceName, Map data) async {
  var responseBody = json.decode('{"data": "", "status": "NOK"}');
  try {
    var response = await http.put(mid.urlBase + '/$_serverApi$serviceName',
        body: json.encode(data),
        headers: {
          'X-mobile-uuid': await _getDeviceIdentity(),
          'X-mobile-token': await mid.getMobileToken(),
          'Content-Type': 'application/json; charset=utf-8'
        });

    if (response.statusCode == 200) {
      responseBody = json.decode(response.body);

      //
      // If we receive a new token, let's save it
      //
      if (responseBody["status"] == "TOKEN") {
        await mid.setMobileToken(responseBody["data"]);

        // Let's change the status to "OK", to make it easier to handle
        responseBody["status"] = "OK";
      }
    }
  } catch (e) {
    // An error was received
    throw new Exception("AJAX ERROR");
  }
  return responseBody;
}

推荐答案

Günter是正确的.Content-Length必须是从字符串编码为字节后,以服务器要求的任何编码形式,字节数组的长度.

Günter is right. Content-Length has to be the length of the byte array after encoding from a String to bytes in whatever encoding you server requires.

有一个名为 http 的软件包,该软件包提供了更高级别的api(它使用dart.io httpClient),它会为您编码帖子的正文和长度.例如,当您需要发送 application/x-www-form-urlencoded 表单时,它甚至会带一个Map并为您完成所有编码(您仍然需要自己编码为json).同样,仅发送 String List< int> 也很高兴.这是一个示例:

There's a package called http which provides a slightly higher level api (it uses dart.io httpClient under the hood) which takes care of encoding the post body and length for you. For example, when you need to send application/x-www-form-urlencoded form it will even take a Map and do all the encoding for you (you still need to encode to json yourself). It's equally happy to send just a String or List<int>. Here's an example:

  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,
  );

这篇关于Flutter:HttpClient发布contentLength-异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆