Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - How to download a file from server using binary stream

Tags:

flutter

dart

I need to be able to download and display an image from a private server. The request that I send needs to include a header with content-type and a body with sessionToken and userId. The server responds with a binary stream with the Content-type application/octet-stream.

This is the code I have right now:

 Future<Null> _downloadFile(String url, String userId, sessionToken) async {
    Map map = {'token': sessionToken, 'UserId': userId};

    try {
      var request = await httpClient.getUrl(Uri.parse(url));
      request.headers.set('content-type', 'application/json');
      request.add(utf8.encode(json.encode(map)));
      var response = await request.close();
      var bytes = await consolidateHttpClientResponseBytes(response);
      await _image.writeAsBytes(bytes);
      userImage(_image);
    }
    catch (value){
      print(value);
    }

  }

When I try to read the response I get this error: HttpException: Content size exceeds specified contentLength. 72 bytes written while expected 0.

I've tried to google this endlessly on how to download a file from a server using a stream, but I can't find anything. What I need is something similar to the bitmap class in .NET that can take in a stream and turn it into an image.

Can anybody help me? It would be greatly appreciated.

like image 603
annalaufey Avatar asked Sep 12 '18 10:09

annalaufey


2 Answers

I was able to do this successfully with this code:

 void getImage(String url, String userId, sessionToken) async{
    var uri = Uri.parse(url);

    Map body = {'Session': sessionToken, 'UserId': userId};
    try {
      final response = await http.post(uri,
          headers: {"Content-Type": "application/json"},
          body: utf8.encode(json.encode(body)));

      if (response.contentLength == 0){
        return;
      }
      Directory tempDir = await getTemporaryDirectory();
      String tempPath = tempDir.path;
      File file = new File('$tempPath/$userId.png');
      await file.writeAsBytes(response.bodyBytes);
      displayImage(file);
    }
    catch (value) {
      print(value);
    }
  }

Thanks for the help :)

like image 163
annalaufey Avatar answered Oct 09 '22 01:10

annalaufey


Here is a related example showing only how to stream the content of a webpage or file:

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

Future<void> main() async {
  final url = Uri.parse('https://google.com/');
  final client = http.Client();
  final request = http.Request('GET', url);
  final response = await client.send(request);
  final stream = response.stream;
  await for (var data in stream) {
    print(data.length);
  }
  client.close();
}

It is a complete example so if you add the http package to your pubspec.yaml file, you can copy the whole thing to test it. The example prints the size of each data chunk coming in. If you want to convert those bytes to a string you could use stream.transform(utf8.decoder).

I'm using the above example to learn how streaming works. A more complete solution would need to handle errors and save the file.

Thanks to this answer for help with this.

See also

  • Difference between http and HttpClient in Dart
like image 41
Suragch Avatar answered Oct 08 '22 23:10

Suragch