Flutter:如何在上传文件时增加 onSendProgress 对流畅进度条动画的调用?

Tom*_*ers 13 file-upload flutter dio flutter-http

我有以下代码来上传文件。

var client = new dio.Dio();
await client.put(
  url,
  data: formData,
  options: dio.Options(
    headers: headers,
  ),
  onSendProgress: (int sent, int total) {
    final progress = sent / total;
    print('progress: $progress ($sent/$total)');
  },
);
Run Code Online (Sandbox Code Playgroud)

上传文件工作正常。问题是,我有一个视图,它有一个圆形进度条,指示onSendProgress触发时的上传进度。当我上传一个 ~10MB 的文件时,进度条会在一秒钟内从 0% 跳到 100%,然后在继续执行其余代码之前等待几秒钟(取决于文件大小)。这对我来说似乎很奇怪,因为我希望进度条会逐渐增加进度。

您可以在下面找到我的示例中的打印输出,其中包含一个 ~10MB 的文件。

flutter: progress: 0.000003035281907563734 (29/9554302)
flutter: progress: 0.000013187776563897604 (126/9554302)
flutter: progress: 0.999996546058519 (9554269/9554302)
flutter: progress: 0.9999967553883057 (9554271/9554302)
flutter: progress: 1.0 (9554302/9554302)
Run Code Online (Sandbox Code Playgroud)

这是一个较小的文件,但具有相同数量的回调。

flutter: progress: 0.00001847214941293598 (29/1569931)
flutter: progress: 0.00008025830434585978 (126/1569931)
flutter: progress: 0.9999789799679094 (1569898/1569931)
flutter: progress: 0.9999802539092483 (1569900/1569931)
flutter: progress: 1.0 (1569931/1569931)
Run Code Online (Sandbox Code Playgroud)

如您所见,它从 0% 跃升至 100%。我可以想象你在想,那只是快速的互联网。但我试过 Wifi、4G、3G,它们都出现了同样的问题。我点击了上传按钮,它从 0% 开始跳到 100%,然后我必须等待一段时间(取决于文件大小)才能完成上传。

有没有办法onSendProgress在上传过程中触发更多的回调或以某种方式延迟上传以便我可以获得平稳的上传进度?

编辑:

我已经尝试使用 HTTP 包进行以下操作

import 'dart:async';
import 'package:http/http.dart' as http;

class UploadRequest extends http.MultipartRequest {
  final void Function(int bytes, int totalBytes) onProgress;

  UploadRequest(
    String method,
    Uri url, {
    this.onProgress,
  }) : super(method, url);

  http.ByteStream finalize() {
    final byteStream = super.finalize();
    if (onProgress == null) return byteStream;

    final total = this.contentLength;

    final t = StreamTransformer.fromHandlers(
      handleData: (List<int> data, EventSink<List<int>> sink) {
        onProgress(data.length, total);
        sink.add(data);
      },
    );

    final stream = byteStream.transform(t);
    return http.ByteStream(stream);
  }
}
Run Code Online (Sandbox Code Playgroud)

扳机:

final request = UploadRequest(
  'PUT',
  Uri.parse(url),
  onProgress: (int bytes, int total) {
    print('progress: $progress ($sent/$total)');
  },
);

request.headers.addAll(headers);
request.files.add(
  http.MultipartFile.fromBytes(
    'file',
    attachment.file.buffer.asUint8List(),
    filename: attachment.name,
    contentType: MediaType.parse(attachment.contentType),
  ),
);


var response = await request.send();
Run Code Online (Sandbox Code Playgroud)

但遗憾的是,这也有同样的问题。文件上传正常,但进度回调只调用了几次。它立即达到 100%,然后我必须等待一段时间(取决于文件大小)才能从服务器获得 2xx 响应。所以我不认为这是一个特定的 DIO 问题。

我认为看起来它实际上并没有显示上传进度,而是显示文件被读入流客户端的进度。然后将流上传到服务器,这就是您正在等待的(当然取决于文件大小),即使进度显示为 100%。

mFe*_*ein 7

这似乎是 上的一个错误dio,我可以看到两种方法可以解决这个问题:

  1. 只需在您的循环进度中添加一个数字,它就会说99%(截断其余部分),以便用户知道它还没有完成,100%只有在您获得1.0结果时才会发生)。

  2. 改用http包。该http包作为StreamedRequest这将使你在东西被发送到了什么,这样你就可以在你的UI反映这种更精细的控制。