如何在Flutter中上传http.MultipartRequest请求上的文件时获取进度事件

时间:2018-12-11 16:00:07

标签: dart flutter dart-http

我正在使用MultipartRequest中的package:http上传文件。我已经成功上传了文件,但是我想获取正在上传的文件的进度。我该如何实现?我当前的代码看起来像这样

Future submitFile(var report, File file) async {
var uri = Uri.parse(endpoint + "v1/reports");
  var request = http.MultipartRequest("POST", uri);
  await addHeaders(request.headers);
  request.fields.addAll(Report.toMap(report));
  if (file != null)
    request.files.add(await http.MultipartFile.fromPath(
      'report_resource',
      file.path,
    ));

  String response = "";
  await (await request.send()).stream.forEach((message) {
    response = response + String.fromCharCodes(message);
  });
  return response;
}

我搜索了解决方案,找到了thisthis的帖子与我要实现的功能有点不同,因为他正在使用不同的客户端进行请求。

也许我没有在正确的路径上搜索。 感谢您的帮助。

4 个答案:

答案 0 :(得分:4)

等待一周左右后。我没有得到回应。因此,我自己开发了一个插件来实现此功能。打包link

使用示例:

var request = MultipartRequest();

request.addFile("image", imagePath);

Response response = request.send();

response.onError = () {
  print("Error");
};

response.onComplete = (response) {
  print(response);
};

response.progress.listen((int progress) {
  print("progress from response object " + progress.toString());
});

注意:此程序包仅适用于android。

答案 1 :(得分:1)

您可以尝试这个类吗,因为我还没有测试它,请让我知道您控制台中打印的任何东西。

class MF extends http.MultipartRequest{
  MF(String method, Uri url) : super(method, url);
  @override
  Future<http.StreamedResponse> send() async {

    var client = new Client();
    int byteCount = 0;
    Stream<List<int>> onDone<T>(Stream<List<int>> stream, void onDone()) =>
        stream.transform(new StreamTransformer.fromHandlers(
            handleDone: (sink) {
              sink.close();
              onDone();
        },
          handleData: (data, sink) {
            byteCount += data.length;
            print(byteCount);
            sink.add(data);
          },
        ),
        );

    try {
      var response = await client.send(this);
      var stream = onDone(response.stream, client.close);
      return new StreamedResponse(new ByteStream(stream), response.statusCode,
          contentLength: response.contentLength,
          request: response.request,
          headers: response.headers,
          isRedirect: response.isRedirect,
          persistentConnection: response.persistentConnection,
          reasonPhrase: response.reasonPhrase);
    } catch (_) {
      client.close();
      rethrow;
    }
  }

}

用法:

代替var request = http.MultipartRequest("POST", uri);

使用:

var request = MF("POST", uri);

答案 2 :(得分:1)

使用dio软件包很容易做到这一点:

Response response;
String filePath="...";
//upload a video
response = await dio.post(
  "/upload",
  data: FormData.from({
    "file": UploadFileInfo(File(filePath), "bee.mp4"),
  }),
  onSendProgress: (received, total) {
    if (total != -1) {
      print((received / total * 100).toStringAsFixed(0) + "%");
    }
  },
);

答案 3 :(得分:0)

这是我的看法:

// multipart_request.dart

import 'dart:async';

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

class MultipartRequest extends http.MultipartRequest {
  /// Creates a new [MultipartRequest].
  MultipartRequest(
    String method,
    Uri url, {
    this.onProgress,
  }) : super(method, url);

  final void Function(int bytes, int totalBytes) onProgress;

  /// Freezes all mutable fields and returns a single-subscription [ByteStream]
  /// that will emit the request body.
  http.ByteStream finalize() {
    final byteStream = super.finalize();
    if (onProgress == null) return byteStream;

    final total = this.contentLength;
    int bytes = 0;

    final t = StreamTransformer.fromHandlers(
      handleData: (List<int> data, EventSink<List<int>> sink) {
        bytes += data.length;
        onProgress(bytes, total);
        sink.add(data);
      },
    );
    final stream = byteStream.transform(t);
    return http.ByteStream(stream);
  }
}

用法:

import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart' show MediaType;

import 'multipart_request.dart';

final uri = 'https://...';
final request = MultipartRequest(
  'POST',
  uri,
  onProgress: (int bytes, int total) {
    final progress = bytes / total;
    print('progress: $progress ($bytes/$total)');
  },
);

request.headers['HeaderKey'] = 'header_value';
request.fields['form_key'] = 'form_value';
request.files.add(
  await http.MultipartFile.fromPath(
    'field_name',
    'path/to/file',
    contentType: MediaType('image', 'jpeg'),
  ),
);

final streamedResponse = await request.send();