Flutter:HttpClient post contentLength - 异常

时间:2018-04-29 17:44:55

标签: flutter

非常奇怪......

为了将一些JSON数据发布到我的服务器,我将contentLength定义为JSON编码数据的长度,但是我接收到一个异常,说明" 内容大小超过指定的contentLength &#34 ;.差异是1个字节。

以下是源代码:

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;
}

其他时候,它运作正常......

我是否对此代码有任何不妥之处?

非常感谢你的帮助。

使用解决方案进行编辑

非常感谢你的帮助。使用utf8.encode(json.encode(data))的简单事实并没有完全奏效。所以,我转向 http 库,它现在就像一个魅力。代码甚至更轻!

以下是代码的新版本:

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;
}

3 个答案:

答案 0 :(得分:1)

看起来您的字符串包含多字节字符。 UTF8-对字符串进行编码以获得正确的长度:

var body = utf8.encode(json.encode(data));

答案 1 :(得分:1)

Günter是对的。 Content-Length必须是从String编码到服务器所需的任何编码的字节后字节数组的长度。

有一个名为http的软件包,它提供了一个稍高级别的api(它使用引擎盖下的dart.io httpClient),负责为你编写帖子体和长度。例如,当您需要发送application/x-www-form-urlencoded表单时,它甚至会为您执行Map并为您执行所有编码(您仍然需要自己编码为json)。只发送StringList<int>也同样高兴。这是一个例子:

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

答案 2 :(得分:0)

我了解了

req.headers.contentLength = utf8.encode(body).length;

Utf8Codec文档的间接提示中指出

  

解码(列出codeUnits,{bool allowMalformed})→字符串

     

将UTF-8 codeUnits(无符号的8位整数列表)解码为相应的字符串。

这意味着utf8.encode()返回codeUnits,实际上意味着List<uint8>

编码字符串有效载荷理论上将返回一个列表,该列表的长度是有效载荷的长度(以字节为单位)。

因此,使用httpClient意味着始终以 bytes 为单位测量有效载荷的长度,而不是可能不同的String的长度。