17

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

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

上传文件工作正常。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)

这个文件较小,但回调数量相同。

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)

如您所见,它从 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);
  }
}

扳机:

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

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

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

4

5 回答 5

7

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

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

  2. 请改用http包。这个httpStreamedRequest可以让你更好地控制发送的内容,所以你可以在你的 UI 上反映这一点。

于 2020-05-31T03:54:49.460 回答
1

我找到了解决方案。

只需在文件中file.openRead()用作请求的data参数PUT

因为MultipartFile也许它可以使用MultipartFile(file.openRead(), file.lenthSync()). 但我没有验证这一点,如果有必要,有人可以尝试一下。

var client = Dio();
await client.put(
  url,
  data: file.openRead(),
  options: dio.Options(
    headers: headers,
  ),
  onSendProgress: (int sent, int total) {
    print('progress: ${(sent / total * 100).toStringAsFixed(0)}% ($sent/$total)');
  },
);

进度回调现在很顺利。

I/flutter (19907): progress: 9% (65536/734883)
I/flutter (19907): progress: 18% (131072/734883)
I/flutter (19907): progress: 27% (196608/734883)
I/flutter (19907): progress: 36% (262144/734883)
I/flutter (19907): progress: 45% (327680/734883)
I/flutter (19907): progress: 54% (393216/734883)
I/flutter (19907): progress: 62% (458752/734883)
I/flutter (19907): progress: 71% (524288/734883)
I/flutter (19907): progress: 80% (589824/734883)
I/flutter (19907): progress: 89% (655360/734883)
I/flutter (19907): progress: 98% (720896/734883)
I/flutter (19907): progress: 100% (734883/734883)
于 2021-11-20T18:06:35.260 回答
0

我遇到了同样的问题。我尝试了几十个技巧,但没有任何效果。我不得不用 MultipartFile.fromFile 替换 MultipartFile.fromBytes。它对我有用。

于 2021-04-15T00:37:44.417 回答
-2

在这个例子中很简单

function dioProcess(processfunction){
 var client = new dio.Dio();
 await client.put(
   url,
   data: formData,
   options: dio.Options(
    headers: headers,
  ),
  onSendProgress: processfunction
}

用法

dioProcess((int sent, int total) {
    final progress = sent / total;
    print('progress: $progress ($sent/$total)');
  },)
于 2020-09-23T01:50:36.607 回答
-2

1. ==使用下面的功能正在工作:==

1.use MultipartFile.fromFile(file.path) 
2.use MultipartFile.fromFileSync(file.path, filename: basename(file.path))

这些百分比也是如此。例如 10%、20%、50%、75% 等。

2. ==使用下面的功能不起作用:==

1.  MultipartFile.fromBytes(fileData)

如您所见,它从 0% 跃升至 100%

示例:我使用 await MultipartFile.fromFile(file.path),onSendProgress 工作正常。

Future<OSSResponse> postObjectWithFile(
    File file,
    String bucketName,
    String fileKey, {
      ProgressCallback onSendProgress,
    ObjectACL acl = ObjectACL.inherited,
  }) async {
    assert(acl != null, "ACL不能为空");
    final OSSCredential credential = await credentialProvider.getCredential();

    FormData formData = FormData.fromMap({
      'Filename': fileKey,
      'key': fileKey, 
      'policy': SignUtil.getBase64Policy(),
      'OSSAccessKeyId': credential.accessKeyId,
      'success_action_status': '200',
      'signature': SignUtil.getSignature(credential.accessKeySecret),
      'x-oss-security-token': credential.securityToken,
      'x-oss-object-acl': acl.parameter,
      'file': await MultipartFile.fromFile(file.path),//change code
    });

    final dio = DioUtil.getDio();
    final res = await dio.post(
      'https://$bucketName.$endpoint',
      options: Options(
        responseType: ResponseType.plain,
      ),
      data: formData,
      onSendProgress: (int sent, int total) {
        final progress = sent / total;
        print('progress: $progress ($sent/$total)');
      },
    );

    return OSSResponse(res.statusCode, res.statusMessage, fileKey);
  }

onSendProgress 正在工作。

于 2021-02-02T09:17:50.733 回答