How to get progress event while uploading file on http.MultipartRequest request in flutter

After waiting for a week or so. I didn't get response. Thus I developed a plugin myself to get this behavior. Package link.

Example to use it:

var request = MultipartRequest();

request.addFile("image", imagePath);

Response response = request.send();

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

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

//Not 100% success
response.progress.listen((int progress) {
  print("progress from response object " + progress.toString());
});

Update Jun 30, 2020

The package now supports iOS as well.


Here is my take:

// 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);
  }
}

Usage:

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