【问题标题】:Flutter: HttpClient post contentLength -- exceptionFlutter:HttpClient post contentLength - 异常
【发布时间】:2018-04-29 17:44:55
【问题描述】:

很奇怪……

为了将一些 JSON 数据发布到我的服务器,我将 contentLength 定义为 JSON 编码数据的长度,但随后我收到一个异常,提示“内容大小超过指定的 contentLength”。差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;
}

【问题讨论】:

    标签: flutter


    【解决方案1】:

    我得到了它的工作

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

    来自Utf8Codec 文档的间接提示

    decode(List codeUnits, { bool allowMalformed }) → String

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

    这意味着utf8.encode() 返回codeUnits 这实际上意味着List&lt;uint8&gt;

    理论上,对 String 有效负载进行编码会返回一个列表,该列表的长度是有效负载的长度(以字节为单位)。

    因此,使用httpClient 意味着始终以字节 为单位测量有效负载的长度,而不是可能不同的字符串长度。

    【讨论】:

      【解决方案2】:

      君特是对的。 Content-Length 必须是从 String 编码为服务器所需的任何编码的字节后的字节数组的长度。

      有一个名为 http 的包,它提供了一个稍微高级一点的 api(它在后台使用 dart.io httpClient),它负责为您编码帖子正文和长度。例如,当您需要发送application/x-www-form-urlencoded 表单时,它甚至会获取一个 Map 并为您完成所有编码(您仍然需要自己编码为 json)。发送StringList&lt;int&gt; 也同样令人高兴。这是一个例子:

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-07-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-18
          • 2020-08-18
          • 1970-01-01
          相关资源
          最近更新 更多