26

I'm trying to convert a network image into a file and the first part of that is to convert it into a Uint8List. Here is how I'm doing this with 1 of my asset images...

      final ByteData bytes = await rootBundle.load('assests/logo');
      final Uint8List list = bytes.buffer.asUint8List();

      final tempDir = await getTemporaryDirectory();
      final file = await new File('${tempDir.path}/image.jpg').create();
      file.writeAsBytesSync(list);

How can I do this with Image.network(imageUrl.com/image)

Charles Jr
  • 8,333
  • 15
  • 53
  • 74

6 Answers6

26

The simplest way seeems to get the http response using the image url and response.bodyBytes would contain the data in Uint8List.

http.Response response = await http.get(
    'https://flutter.io/images/flutter-mark-square-100.png',
);   
response.bodyBytes //Uint8List

Now you can do things like converting to base64 encoded string base64.encode(response.bodyBytes);
Update: With newer version of http, you need to add Uri.parse()
Eg.

http.Response response = await http.get(
    Uri.parse('https://flutter.io/images/flutter-mark-square-100.png'),
);
Kunchok Tashi
  • 2,413
  • 1
  • 22
  • 30
lordvcs
  • 2,466
  • 3
  • 28
  • 37
  • Using this method to get a File as File file = File.fromRawPath(uint8list); I get the following error : The following FileSystemException was thrown resolving an image codec: Cannot open file, path = '.....' – Ant D Jan 03 '20 at 03:50
  • 1
    The problem with this answer is that it downloads the file again regardless of it being in cache or not, causing users to wait and diminishing UX. – yoni keren Nov 03 '22 at 23:35
11

I figured out a different solution. Hope it helps someone.

import 'dart:typed_data';
import 'package:flutter/services.dart';

Uint8List bytes = (await NetworkAssetBundle(Uri.parse(imageUrl))
            .load(imageUrl))
            .buffer
            .asUint8List();
Ujjwal Raijada
  • 867
  • 10
  • 21
  • 2
    Seems like not working for Flutter Web (3.0.5), error shows Unsupported operation: Platform._version. Same problem here : https://stackoverflow.com/questions/60435601/how-to-download-image-from-network-and-use-as-an-asset-image-offline-in-flutter – Lal Oct 24 '22 at 21:08
7
  void initState() {
    super.initState();
    var sunImage = new NetworkImage(
        "https://resources.ninghao.org/images/childhood-in-a-picture.jpg");
    sunImage.obtainKey(new ImageConfiguration()).then((val) {
      var load = sunImage.load(val);
      load.addListener((listener, err) async {
        setState(() => image = listener);
      });
    });
  }

See also https://github.com/flutter/flutter/issues/23761#issuecomment-434606683

Then you can use image.toByteData().buffer.asUInt8List()

See also https://docs.flutter.io/flutter/dart-ui/Image/toByteData.html

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I'm revisiting your answer and now i'm getting an error on buffer that it isn't defined for ByteData when I use the following code... `final Uint8List list = image.image.toByteData().buffer.asUInt8List();`. Am I missing something? Please help. – Charles Jr Mar 08 '19 at 21:25
  • 3
    @CharlesJr image.image.toByteData() returns Future. `ByteData data = await mage.image.toByteData(); data.buffer.asUInt8List();` – Volker Fried Apr 12 '19 at 06:52
  • 1
    I have error with sunImage.load(val). The error is 2 positional argument(s) expected, but 1 found. Can I know how to solve it? – qing Apr 03 '20 at 06:22
  • Seems the API has changed. Check what the 2nd parameter id that the `load` function expects. – Günter Zöchbauer Apr 03 '20 at 06:47
  • @syonip Some more details would be helpful. Any error message? – Günter Zöchbauer May 26 '20 at 08:40
  • my obtainKey() returns _SizeAwareCacheKey, but bundle.load() expects String – temirbek Jun 03 '20 at 10:02
2

After trying for hours this is what helped me

import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';

Future<File> getFileFromNetworkImage(String imageUrl) async {
  var response = await http.get(imageUrl);
  final documentDirectory = await getApplicationDocumentsDirectory();
  String fileName = DateTime.now().millisecondsSinceEpoch.toString();
  File file = File(path.join(documentDirectory.path, '$fileName.png'));
  file.writeAsBytes(response.bodyBytes);
  return file;
}

final file = await getFileFromNetworkImage("<your network image Url here>");

Note: this also converts mp4 videos to a File.

originally answered here

Mahesh Jamdade
  • 17,235
  • 8
  • 110
  • 131
1

The answers here are relevant and help explain how dart and flutter image compression/conversion works. If you would like a shortcut, there is this package https://pub.dev/packages/network_image_to_byte that makes it really easy.

Charles Jr
  • 8,333
  • 15
  • 53
  • 74
1

As http needs Uri this would be helpful: you should remove the begining serverAddress from your ImageAddress first : something like this in my case that I have 3001 in my url:

    String serverAddress = 'myAddress.com:3001';
    int indexOf3001 = imageAddress.indexOf('3001');
    String trimmedImageAddress= imageAddress.substring(indexOf3001 + 4);

then :

    var imageUrl = Uri.https(serverAddress, trimmedImageAddress);
    final http.Response responseData = await http.get(imageUrl);
    Uint8List imageBytes = responseData.bodyBytes;

this works on device and web too, hope it can help.

Ali Esfandiari
  • 316
  • 4
  • 13