首页 > 解决方案 > 如何取消在 Flutter 中使用 http.MultipartRequest() 发送的正在进行的文件上传?

问题描述

我正在尝试在我的 Flutter 应用程序中添加取消功能来上传文件。我目前正在使用http.MultipartRequest()fromhttp package上传文件。我已尝试使用打包上传,CancelableOperation但它只会取消我的 Flutter 应用程序中的内部进程,并且文件仍会成功上传到我的 Firebase 存储服务器。

我在 http 包上阅读了关于http.Client()在 http 请求完成后使用和关闭它的 README.md。我正在考虑使用http.Client()上传文件,然后用 关闭它http.Client().close()以取消 http 请求。

但是,我还没有找到上传文件的正确方法http.Client。我在 Google 和 stackoverflow 上浏览过它,但所有帖子都建议使用http.MultipartRequest(). 其中一个帖子

所以,我的问题是: 1. 是否可以取消http.MultipartRequest()从 Flutter 中的 http 包发送的上传文件?2. 我是否在尝试使用的正确轨道上http.Client()?或者有没有更好的方法来做到这一点?3.如果使用http.Client()是唯一的方法,那么你能告诉我如何上传文件http.Client()吗?因为它只有post()和没有multipartrequest()

对不起,很长的文字。请帮忙。谢谢!

标签: httpfile-uploaddartflutter

解决方案


包在引擎盖下http使用。HTTPClient它将底层客户端包装在一个IOClient. 大多数http's 方法(如getand post)允许您传入自己的客户端,但MultipartRequest不允许(它为每个请求创建一个)。

最简单的解决方案似乎是对其进行子类化。

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

推荐阅读