Skip to content

使用dio发送的请求体为Uint8List格式时,转换器将Uint8List转化为String的问题。 #371

Closed
@jianzi0307

Description

@jianzi0307

最近做的一个项目用到protobuf,使用dio发送的post请求数据为Uint8List格式:

UserMeRequest req = UserMeRequest.create();
req.token = await Storage.getToken();
Uint8List reqBuffer = req.writeToBuffer();
Uint8List responseBuffer = await dio.post('user/me', data: reqBuffer);  // <------
UserMeResponse resp = UserMeResponse.fromBuffer(responseBuffer);
print('$resp <<<<<<<<<<<<<<userMe');

服务端总提示protobuf数据格式不正确,跟踪代码我发现dio转换器总是返回String格式:
DefaultTransformer 返回的数据将data转化为String类型。

Future<String> transformRequest(RequestOptions options) async {
    var data = options.data ?? "";
    if (data is! String) {
      if (options.contentType.mimeType == ContentType.json.mimeType) {
        return json.encode(options.data);
      } else if (data is Map) {
        return Transformer.urlEncodeMap(data);
      }
    }
    return data.toString();  /// <=================== 调用了data.toString()方法
  }

这样会导致服务端处理的时候将接收的字节数组按照字符串处理,导致格式无法识别。

建议:
能否添加Uint8List格式的判断,不做处理直接返回data,

像这样:

Future<dynamic> transformRequest(RequestOptions options) async {
    var data = options.data ?? "";
    if (data is! String) {
      if (options.contentType.mimeType == ContentType.json.mimeType) {
        return json.encode(options.data);
      } else if (data is Map) {
        return Transformer.urlEncodeMap(data);
      } else if (data is Uint8List) {  /// <========= 添加Uint8List格式判断条件
        return data;
      }
    }
    return data.toString();  
  }

Activity

jianzi0307

jianzi0307 commented on Jul 9, 2019

@jianzi0307
Author
class Uint8ListTransformer extends DefaultTransformer {
  @override
  Future<String> transformRequest(RequestOptions options) async {
    if (options.data is Uint8List) {
      return String.fromCharCodes(options.data);
    } else {
      return super.transformRequest(options);
    }
  }
}

BaseOptions options = BaseOptions(
   baseUrl: "https://xxxx.com/",
   ......
   requestEncoder: (String request, RequestOptions options) {
        Uint8List list = Uint8List.fromList(request.codeUnits);
        return list;
    },
);
Dio dio = Dio(options);
dio.transformer = Uint8ListTransformer();
......
nextwhale

nextwhale commented on Nov 14, 2020

@nextwhale

You can create a method to transform proto buffer to Stream like this:

    dynamic transformPbMessage2Steam(GeneratedMessage pbMessage) {
        List<int> buffer = pbMessage.writeToBuffer();
        return Stream.fromIterable([buffer]);
    }

The usage example:

    var model = HelloRequest();
    model.id = '100288273';
    model.name = '我住隔壁我姓王';
    
    var res = await Dio().post('/', data: transformPbMessage2Steam(model));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jianzi0307@nextwhale

        Issue actions

          使用dio发送的请求体为Uint8List格式时,转换器将Uint8List转化为String的问题。 · Issue #371 · cfug/dio