Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
jianzi0307 opened this issue Jul 9, 2019 · 2 comments

Comments

@jianzi0307
Copy link

jianzi0307 commented Jul 9, 2019

最近做的一个项目用到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();  
  }
@jianzi0307
Copy link
Author

jianzi0307 commented Jul 9, 2019

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
Copy link

nextwhale commented Nov 14, 2020

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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants