Jaeger
Jaeger

Reputation: 371

Flutter DIO: upload image using binary body with Dio package

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

Upvotes: 10

Views: 19305

Answers (7)

Arenukvern
Arenukvern

Reputation: 534

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),
);

Upvotes: 2

Muhammad Ahsan
Muhammad Ahsan

Reputation: 11

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
));

Upvotes: 1

sultanmyrza
sultanmyrza

Reputation: 5392

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
);

Upvotes: 5

Anirban Das
Anirban Das

Reputation: 1265

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
);

Upvotes: 16

Angelo Montil
Angelo Montil

Reputation: 17

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',
        },
      ),
    );

Upvotes: 0

Mehul Prajapati
Mehul Prajapati

Reputation: 1260

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(),
);

Upvotes: 6

Haroon Ashraf Awan
Haroon Ashraf Awan

Reputation: 1219

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}")
                                ));

Upvotes: 2

Related Questions