【问题标题】:Flutter upload large file with progress bar. App and Web both supportFlutter 上传带有进度条的大文件。 App 和 Web 都支持
【发布时间】:2021-06-23 04:49:49
【问题描述】:

我遇到上传大文件的问题。当从应用程序上传文件工作正常但网络挂起时,为 Web 和应用程序(本机)编译的颤振应用程序。如何将大文件作为流请求发送。

我是 Flutter 的新手,正在开发当前现有的应用程序,该应用程序具有上传大型教程视频文件和 PDF 文件的功能。要求是在上传文件的过程中显示进度条,目前应用程序我使用了dio,但它在网页版中挂起,而不是文件不上传操作失败。

  • 文件大小约为 400MB 到 700MB

目前使用以下包

dependencies:
  http: ^0.12.2
  dio: ^3.0.10

你能帮我解决这个问题吗?

我正在尝试使用以下代码来实现,但有些代码无法正常工作。 https://github.com/salk52/Flutter-File-Upload-Download

抛出“内存缓冲区分配失败”之类的错误,由于其他包干扰,我无法更新dio或http的版本。不知何故,我必须使用httpclientdio 来实现它。我无法更新包的版本,因为它弄乱了其他包的依赖关系。

示例参考。代码如下: 文件大小约为 500 MB 到 700MB

对于参考。以下代码在代码中使用。

Dio封装示例:

#Dio example start

  Future<NormalResponse> addSubjectMaterial(
      {GetSubjectMaterial objSubMat,
      bool isDelete,
      PlatformFile objfile,
      Function sendProgress,
      Function receiveProgress,
      dio.CancelToken cancelToken}) async {
    NormalResponse objRes = NormalResponse();
    try {
      print(objSubMat.objMaterial.subjectId);
      dio.FormData formData = dio.FormData();
      formData.fields.add(MapEntry("ObjSubMat", json.encode(objSubMat)));
      formData.fields.add(MapEntry("IsDelete", isDelete.toString()));
      formData.fields
          .add(MapEntry("ClassesId", AppConstants.classesId().toString()));
      if (objfile != null) {
        formData.files.add(
            MapEntry("objfile", await getMultipartFile(objfile, "objfile")));
      }
      var resp = await dio.Dio().post(
        AppConstants.addUpdateSubjectMaterial,
        data: formData,
        options: requestConfig,
        cancelToken: cancelToken,
        onSendProgress: sendProgress,
        onReceiveProgress: receiveProgress,
      );

      // String respStr = resp.toString();
      // objRes = NormalResponse.fromJson(json.decode(respStr));
      objRes = NormalResponse.fromJson(resp.data);
    } catch (err) {
      objRes.err = err.toString();
      objRes.isSuccess = false;
      objRes.newId = -1;
      sendProgress = null;
      receiveProgress = null;
    }
    return objRes;
  }

#Dio example end

#httpclient example code is there any solution with progress bar in this sample code.

   Future<NormalResponse> addUpdateSubjectMaterialHttp(
       {GetSubjectMaterial objSubMat,
       bool isDelete,
       PlatformFile objfile,
       Function sendProgress,
       Function receiveProgress,
       dio.CancelToken cancelToken}) async {
     NormalResponse objRes = NormalResponse();
     try {
       var req = http.MultipartRequest(
         "POST",
         Uri.parse(AppConstants.addUpdateSubjectMaterial),
       );
       req.headers.addAll({
         'Content-type': 'application/json',
         'Accept': 'application/json',
       });
       req.fields['ObjSubMat'] = json.encode(objSubMat);
       req.fields['IsDelete'] = isDelete.toString();
       req.fields['ClassesId'] = AppConstants.classesId().toString();

       if (objfile != null) {
         req.files.add(http.MultipartFile(
             "objFile", objfile.readStream, objfile.size,
             filename: objfile.name));
       }

       var resp = await req.send();
       String result = await resp.stream.bytesToString();
       objRes = NormalResponse.fromJson(json.decode(result));
       print(objRes.isSuccess);
       print(objRes.err);
       print("Here done");
     } catch (err) {
       print(err);
       throw err;
     }
     return objRes;
   }
   
#httpclient


Http package example:

#example start

  Future<NormalResponse> addSubjectMaterial(
      {GetSubjectMaterial objSubMat,
      bool isDelete,
      PlatformFile objfile,
      Function sendProgress,
      Function receiveProgress,
      dio.CancelToken cancelToken}) async {
    NormalResponse objRes = NormalResponse();
    try {
      print(objSubMat.objMaterial.subjectId);
      dio.FormData formData = dio.FormData();
      formData.fields.add(MapEntry("ObjSubMat", json.encode(objSubMat)));
      formData.fields.add(MapEntry("IsDelete", isDelete.toString()));
      formData.fields
          .add(MapEntry("ClassesId", AppConstants.classesId().toString()));
      if (objfile != null) {
        formData.files.add(
            MapEntry("objfile", await getMultipartFile(objfile, "objfile")));
      }
      var resp = await dio.Dio().post(
        AppConstants.addUpdateSubjectMaterial,
        data: formData,
        options: requestConfig,
        cancelToken: cancelToken,
        onSendProgress: sendProgress,
        onReceiveProgress: receiveProgress,
      );

      // String respStr = resp.toString();
      // objRes = NormalResponse.fromJson(json.decode(respStr));
      objRes = NormalResponse.fromJson(resp.data);
    } catch (err) {
      objRes.err = err.toString();
      objRes.isSuccess = false;
      objRes.newId = -1;
      sendProgress = null;
      receiveProgress = null;
    }
    return objRes;
  }

#example end

【问题讨论】:

    标签: flutter httprequest httpclient


    【解决方案1】:

    您必须使用 Future、await 和 async,它们在后台线程中继续流的任务,同时您的应用程序的 UI 工作顺利。

    【讨论】:

    • 能否提供一些示例代码。
    • 好的@DharmeshChauhan 我正在编辑我的答案,但请回复您使用什么来存储数据,firebase 或其他任何东西或 mysql
    • 您好 Manav,感谢您的回复。我正在使用 API 调用它。在 App 版本中,它也可以与简单的 HTML 页面一起正常工作。
    • @DharmeshChauhan 当我通读您的代码时,您似乎已经正确地实现了所有的东西。我有一个建议为 web 构建一个版本,然后尝试,因为您正在尝试调试模式。谢谢。
    猜你喜欢
    • 2014-03-03
    • 2021-05-18
    • 1970-01-01
    • 2013-03-08
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 2011-09-11
    相关资源
    最近更新 更多