9

With thwe http package I can send an image to a server by putting te binary data in the body of a post call like in the snippet of this code:

var response = await http.post('My_url', body: File(path).readAsBytesSync(),  headers: {
                    'apikey': 'myAPIKEY',
                    'Content-Type': 'image/*', // set content-length
                  });

I can't do the same thing by using Dio, I don't know how to put directly the binary data in the body (like i can do it with postman)

postman

Jaeger
  • 331
  • 1
  • 2
  • 11

7 Answers7

13

I also faced the same you have. In DIO you have to send the binary data through streams. Here is the example how I achieved it,

Uint8List image = File(path).readAsBytesSync();

Options options = Options(
  contentType: lookupMimeType(path),
  headers: {
    'Accept': "*/*",
    'Content-Length': image.length,
    'Connection': 'keep-alive',
    'User-Agent': 'ClinicPlush'
  }
);

Response response = await dio.put(
  url,
  data: Stream.fromIterable(image.map((e) => [e])),
  options: options
);
Anirban Das
  • 1,035
  • 1
  • 18
  • 22
  • I will just add that to use the `lookupMimeType()` method you need to import the mime package: `import 'package:mime/mime.dart';` – Radomir Epur Nov 10 '21 at 16:57
  • Worked for me but when I try to upload image which 24 MB it crashed probably due to Stream.fromIterable(image.map((e) => [e])) – sultanmyrza Nov 17 '21 at 08:23
5

Anirban Das solutions is working however when I tried to upload 24MB photo file it crashed probably due to

Stream.fromIterable(image.map((e) => [e]))

So instead I tried to directly read file as stream file.OpenRead() => which returns Strea<List<in>>>

accendent or not but upload speed also increased (maybe becase when you map e => [e] it were slowing down sending data) but who know maybe I'm wrong

So final code for me is

Uint8List image = File(path).readAsBytesSync();

Options options = Options(
  contentType: lookupMimeType(path),
  headers: {
    'Accept': "*/*",
    'Content-Length': image.length,
    'Connection': 'keep-alive',
    'User-Agent': 'ClinicPlush'
  }
);

Response response = await dio.put(
  url,
  data: file.openRead(), <--- change here
  options: options
);
sultanmyrza
  • 4,551
  • 1
  • 30
  • 24
4

Just putting my solution if someone stumbles upon the same issue.

I had to upload the file at a signed google storage URL. API required to insert the file binary data in the body of the PUT request. Couldn't implement using the DIO plugin, I resolved the issue using the DART HTTP package, Below is a sample code.

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

await http.put(
  Uri.parse(uploadURL),
  headers: {
    'Content-Type': mimeType,
    'Accept': "*/*",
    'Content-Length': File(filePath).lengthSync().toString(),
    'Connection': 'keep-alive',
  },
  body: File(filePath).readAsBytesSync(),
);
Mehul Prajapati
  • 1,210
  • 2
  • 11
  • 29
  • This saved the day! Not sure why DIO struggles to handle this, but good ol fashion dart http handles it. DIO did do the upload but only pushed the byte array, which was not helpful. Thanks! – ChillBroDev Mar 25 '21 at 15:29
3

I have declared a FormData object named 'data' and have a map of image with key as filename and value as filepath. 'image' is the key defined on the server side.

 data.files.add(MapEntry(
    'image',
      await MultipartFile.fromFile(image.values.first, filename: "${image.values.first.split("/").last}")
                                ));
Haroon Ashraf Awan
  • 1,201
  • 1
  • 6
  • 15
1

I kept getting http 403 when using dio package to upload binary data to google storage api. I was able to fix this using :

      Response responseGoogleStorage = await dio.put(
      googleStorage.url,
      data: File(_imageFile.path).readAsBytesSync(),
      options: Options(
        headers: {
          'Content-Type': contentType,
          'Accept': "*/*",
          'Content-Length': File(_imageFile.path).lengthSync().toString(),
          'Connection': 'keep-alive',
        },
      ),
    );
Dharman
  • 30,962
  • 25
  • 85
  • 135
  • Thanks a lot! this saved the day! Not really wanted to use good old http just for one request! Same scenario as you, uploading data to Google Storage and getting a 403 response. – David_E Nov 12 '21 at 21:01
0

After combining multiple answers, this solution finally worked for me:

var len = await image.length();
var response = await dio.put(url,
    data: image.openRead(),
    options: Options(headers: {
      Headers.contentLengthHeader: len,
      "Content-Type": "image/jpg",
    } // set content-length
));
0

As some people previously commented, dio really is converting to string, and in my case, that was the problem.

As a solution I've replaced the whole request body by uint8List and it worked.

final uint8List = file.readAsBytesSync();
await _dio.put(
  url,
  options: Options(
    requestEncoder: (final request, final options) {
      return uint8List;
    },
    headers: {
      Headers.contentLengthHeader: '$length',
      Headers.contentTypeHeader: contentType,
    },
  ),
  data: uint8List,
  onSendProgress: (final count, final total) => onProgress(count / total),
);
Arenukvern
  • 438
  • 6
  • 11