How to cancel ongoing file upload sent with http.MultipartRequest() in Flutter?

3,657

Package http uses HTTPClient under the hood. It wraps that underlying client in an IOClient. Most of http's methods (like get and post) allow you to pass in your own client, but the MultipartRequest doesn't (it creates one for each request).

The easiest solution seems to be to subclass it.

import 'dart:async';
import 'dart:io';

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

class CloseableMultipartRequest extends http.MultipartRequest {
  http.IOClient client = http.IOClient(HttpClient());

  CloseableMultipartRequest(String method, Uri uri) : super(method, uri);

  void close() => client.close();

  @override
  Future<http.StreamedResponse> send() async {
    try {
      var response = await client.send(this);
      var stream = onDone(response.stream, client.close);
      return new http.StreamedResponse(
        new http.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;
    }
  }

  Stream<T> onDone<T>(Stream<T> stream, void onDone()) =>
      stream.transform(new StreamTransformer.fromHandlers(handleDone: (sink) {
        sink.close();
        onDone();
      }));
}
Share:
3,657
Admin
Author by

Admin

Updated on December 08, 2022

Comments

  • Admin
    Admin over 1 year

    I'm trying to add cancel functionality to file upload in my Flutter app. I'm currently using http.MultipartRequest() from http package to upload the file. I've tried wrapping the upload with CancelableOperation but it only cancels the internal process within my Flutter app and the file still gets uploaded successfully to my Firebase Storage server.

    I read the README.md on http package about using http.Client() and closing it after the http request is completed. I'm thinking about using http.Client() to upload the file and then closing it with the http.Client().close() to cancel the http request.

    But, I haven't found the right way to upload file with http.Client yet. I browsed about it on Google and stackoverflow but all the posts recommend using http.MultipartRequest(). One of the posts

    So, my questions are: 1. Is it possible to cancel upload file sent with http.MultipartRequest() from http package in Flutter? 2. Am I in the right track with trying to use http.Client() ? Or is there any better way to do this? 3. If using http.Client() is the only way, then can you please show me how to upload file with http.Client()? since it only has post() and no multipartrequest().

    Sorry for the long text. Please help. Thanks!

  • Admin
    Admin over 5 years
    Thank you so much @Richard Heap, it works like a charm! Thank you for taking your time to give me such detailed answer. I really appreciated it :)
  • Jon Scalet
    Jon Scalet about 4 years
    @Richard This solution works if the http client is recreated with every new instance of CloseableMultipartRequest. However, it wouldn't support a reference to a client instance, in that case, it's not a good idea to close the connection to cancel the request.