jonataslaw / getx

Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
MIT License
10.35k stars 1.63k forks source link

[GetConnect] how to download a file? #846

Open xyzbilal opened 3 years ago

xyzbilal commented 3 years ago

Hi, I am trying to download an image from network but I am getting error that stream is already listened to. my function is

 get(
          url,
          headers: headers,
        ).then((response) async {
          await getApplicationDocumentsDirectory().then((path) async {
            File file = new File('$path/file');
             response.bodyBytes.listen((value) {
               file.writeAsBytesSync(value);
             });

          });
        });

error ;

[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: Bad state: Stream has already been listened to.
#0      _StreamController._subscribe (dart:async/stream_controller.dart:710:7)
#1      _ControllerStream._createSubscription (dart:async/stream_controller.dart:860:19)
#2      _StreamImpl.listen (dart:async/stream_impl.dart:493:9)
#3      new _ForwardingStreamSubscription (dart:async/stream_pipe.dart:118:10)
#4      _ForwardingStream._createSubscription (dart:async/stream_pipe.dart:88:16)
#5      _ForwardingStream.listen (dart:async/stream_pipe.dart:83:12)
#6      _HttpIncoming.listen (dart:_http/http_impl.dart:163:8)
#7      _HttpClientResponse.listen (dart:_http/http_impl.dart:427:19)
#8      StreamView.listen (dart:async/stream.dart:1871:20)
#9      Network.requests.<anonymous closure>.<anonymous closure>
package:ulakBEL/utils/network_helper.dart:199
#10     _rootRunUnary (dart:async/zone.dart:1198:47)
#11     _CustomZone.runUnary (dart:async/zone.dart:1100:19)

I also tried like this file.writeAsBytesSync(response.bodyBytes); and of course it gives the error of;

lib/utils/network_helper.dart:200:47: Error: The argument type 'BodyBytes' can't be assigned to the parameter type 'List<int>'.
 - 'BodyBytes' is from 'package:get/get_connect/http/src/request/request.dart' ('../../DevelopmentTools/flutter/.pub-cache/hosted/pub.dartlang.org/get-3.21.3/lib/get_connect/http/src/request/request.dart').
 - 'List' is from 'dart:core'.
               file.writeAsBytesSync(response.bodyBytes);

also I tried,

  final bytes = await response.bodyBytes.toBytes();
             file.writeAsBytesSync(bytes);

and get the same error that says Unhandled Exception: Bad state: Stream has already been listened to.

I was running this with http package like below ;

Future<dynamic> downloadImage(String suffix) async {
    var response = await http.get(url + suffix);
    await getApplicationDocumentsDirectory().then((dir) {
         File profilePic = File(dir.path + '/profilePic.png');
      profilePic.writeAsBytesSync(response.bodyBytes);
    });
  }

when I check bodyBytes in http package it defined asUint8List that implements List<int> but bodyBytes in your package is extends extends StreamView<List<int>>

I also use download method of dio package likebelow;

 await dio.download(
        urls,
        filePath,
        onReceiveProgress: (downloaded, total) {
          double percentage = downloaded / total * 100;
          biggerChild.value = Center(
              child: Text(
            'Yükleniyor .. :  ' + percentage.round().toString(),
            style: TextStyle(color: shared.primaryTextColor()),
          ));
        },
      );

this method directly saves files to filepath and with File widget I can show my downloaded image. also showing download progress is also nice feature. I tried to implement this to your codes but I could not success. I guess I am not professional enough for this area. It would great if Get connect also has this kind of features. thanks for your efforts.

Ridtt commented 3 years ago

We need receive progress. Forced to use dio in pair with GetConnect only because download progress is necessary in large request cases. And you never know then you will have to download something in development cycle of you app. Without onReceiveProgress, you will always have to use dio in any case you need something to fetch bigger then 5mb~. And its not you always want to do when you have your API's configured with auth + interceptors + serializers + nice looking requests in GetConnect. Distracting. P.S. I like getx infrastructure, best what I have found in flutter after 1 year commercial development.

renolation commented 3 years ago

so we have to use dio to download ?

wengxianxun commented 3 years ago

yes, need download action

kauemurakami commented 2 months ago

I'm simply using an alternative solution with url launcher to download files, very simple and quick to implement

if (await launchUrl(Uri.parse(downloadUrl),
              mode: LaunchMode.externalApplication)) {  
          } else {
            ...
          }