Dio分析-Fetch过程分析

流程图

整个Fetch过程依赖的是三个组件的共同作用,
Interceptors,包括RequestInterceptors, ResponseInterceptor,ErrorInterceptor实现整个逻辑过程的流转和控制。参考Dio Interceptor分析
HttpClientAdapter,实现底层socket的建立和数据发送接收流程,主要涉及openurl, close, request stream写入和response stream读取的过程.参考Dio clientAdapter分析
Transformer,实现同步数据转换逻辑,实现请求数据转换和stream处理,响应数据转换和stream处理,参考Dio Transform分析
简单处理流程

上传数据流

Dio上传逻辑主要是通过RequestOption.data通过FormData结构来实现,

FormData用于创建multipart/form-data数据写入流,用于向http服务器提供forms和file.主要参数是fields和files.这里引入了MultipartFile,用于实现文件分块传递。

/// A class to create readable "multipart/form-data" streams.
/// It can be used to submit forms and file uploads to http server.
class FormData {
/// The form fields to send for this request.
  final fields = <MapEntry<String, String>>[];

  /// The [files].
  final files = <MapEntry<String, MultipartFile>>[];
}

FormData的构造器主要是fromMap

FormData.fromMap(
    Map<String, dynamic> map, [
    ListFormat collectionFormat = ListFormat.multi,
    this.camelCaseContentDisposition = false,
  ])

实际应用例子

final formData = FormData.fromMap({
    'age': 25,
    'file': await MultipartFile.fromFile(
      './example/upload.txt',
      filename: 'upload.txt',
    )
  });

  // Send FormData
  response = await dio.post('/test', data: formData);
  print(response);

FormData类主要实现http协议传输的约定,

对传入的map数据编码
在请求头部添加Content-Disposition
如果是文件传输,在请求头部添加filename,根据file.contentype对contenttype进行变更,根据file.headers对请求头部添加相应字段
添加–$boundary\r\n实现数据块分界。

FormData.finalize实现stream的生成(fields和files),提供给dio.transformdata实现请求body数据写入逻辑。

Stream<List<int>> finalize() {
    if (isFinalized) {
      throw StateError(
        'The FormData has already been finalized. '
        'This typically means you are using '
        'the same FormData in repeated requests.',
      );
    }
    _isFinalized = true;
    final controller = StreamController<List<int>>(sync: false);
    void writeAscii(String string) {
      controller.add(utf8.encode(string));
    }

    void writeUtf8(String string) => controller.add(utf8.encode(string));
    void writeLine() => controller.add([13, 10]); // \r\n

    for (final entry in fields) {
      writeAscii('--$boundary\r\n');
      writeAscii(_headerForField(entry.key, entry.value));
      writeUtf8(entry.value);
      writeLine();
    }

    Future.forEach<MapEntry<String, MultipartFile>>(files, (file) {
      writeAscii('--$boundary\r\n');
      writeAscii(_headerForFile(file));
      return writeStreamToSink(
        file.value.finalize(),
        controller,
      ).then((_) => writeLine());
    }).then((_) {
      writeAscii('--$boundary--\r\n');
      controller.close();
    });
    return controller.stream;
  }

multipart数据传输协议约定

MultipartFile

下载数据流

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值