How to send an image to an api in dart/flutter?
Asked Answered
F

4

22

I saw other questions, but thats not what i want, i dont want to upload an image to a server, i dont want to convert to base64...

I only want to post a file in a form data or something else and get the returned info.

i have this, but has not work:

  void onTakePictureButtonPressed() {
    takePicture().then((String filePath) {
      if (mounted) {
        setState(() {
          imagePath = filePath;
          videoController?.dispose();
          videoController = null;
        });

        http.post('http://ip:8082/composer/predict', headers: {
          "Content-type": "multipart/form-data",
        }, body: {
          "image": filePath,
        }).then((response) {
          print("Response status: ${response.statusCode}");
          print("Response body: ${response.body}");
        });


        if (filePath != null) showInSnackBar('Picture saved to $filePath');
      }
    });
  }
Fishtail answered 3/7, 2018 at 19:43 Comment(0)
C
43

The simplest method would be to post a multipart request like in this post and then post it to the server.

Make sure to import these in the beginning of the file:

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

Add this class somewhere in your code:

upload(File imageFile) async {    
      // open a bytestream
      var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
      // get file length
      var length = await imageFile.length();

      // string to uri
      var uri = Uri.parse("http://ip:8082/composer/predict");

      // create multipart request
      var request = new http.MultipartRequest("POST", uri);

      // multipart that takes file
      var multipartFile = new http.MultipartFile('file', stream, length,
          filename: basename(imageFile.path));

      // add file to multipart
      request.files.add(multipartFile);

      // send
      var response = await request.send();
      print(response.statusCode);

      // listen for response
      response.stream.transform(utf8.decoder).listen((value) {
        print(value);
      });
    }

Then upload using:

upload(File(filePath));

In your code:

void onTakePictureButtonPressed() {
    takePicture().then((String filePath) {
      if (mounted) {
        setState(() {
          imagePath = filePath;
          videoController?.dispose();
          videoController = null;
        });

       // initiate file upload
       Upload(File(filePath));

        if (filePath != null) showInSnackBar('Picture saved to $filePath');
      }
    });
  }
Chipper answered 3/7, 2018 at 20:23 Comment(7)
I wrote a few comments to the code I posted. Basically it opens a reads the file into the bytestream, adds it to a multipart request and then sends it as a post request. All you have to do is include this class somewhere in your code and call it.Chipper
@MetaCode you need to import the package import 'package:async/async.dart'; instead of import 'dart:async';. And this one: import 'dart:convert';.Chipper
Well ok, you can/should name it with a lower case character: upload(...) instead of Upload(...). See the edited post.Chipper
I want to add one field with my multipartrequest like request .fields['name'] = DateTime.now().toIso8601String(); But, it's giving me error every time. But, if i give it a static value like request .fields['name'] = "test.png" it work. Can anybody tell me what i am doing wrong ?Mcdougall
is it possible to add headers?Muldoon
@Muldoon Yes, check out the headers option in the docs about the MultipartRequest.Chipper
How to send file as binaryToque
P
5
 import 'package:dio/dio.dart'; //From 3.x.x version

    uploadImage(){
        var formData = FormData();
        formData.files.add(MapEntry("Picture", await MultipartFile.fromFile(data.foto.path, filename: "pic-name.png"), ));
        var response = await dio.client.post('v1/post', data: formdata);
    }
Poisson answered 29/10, 2019 at 17:46 Comment(1)
A little note: when sending an array of files to a spring boot application (which doesn't need something like "pictures[]" notation), I've found useful to follow the instructions here: github.com/flutterchina/dio#multiple-files-upload - read if you don't want "[]"Ascetic
L
4

If you are sending the image to PHP Laravel Server. Try reducing the size of the image while sending it to the server. I used Image Picker package to reduce the size of the image.

var image = await ImagePicker.pickImage(source: imageSource, imageQuality: 50, maxHeight: 500.0, maxWidth: 500.0);

Then create a multipart file with that image, add it to form data, and send the form data to the server using post request with dio library. See @Elialber Lopes answer for sending the data.

It worked for me.

Lorikeet answered 6/6, 2020 at 5:19 Comment(0)
E
1
import 'dart:convert';
import 'package:http/http.dart' as http;

Future<void> sendImage(String apiUrl, String imagePath) async {
  // Convert image to bytes
  var bytes = await rootBundle.load(imagePath);
  var buffer = bytes.buffer;
  var imageBytes = buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes);

  // Encode the bytes
  var base64Image = base64Encode(imageBytes);

  // Send the API request
  var response = await http.post(apiUrl, body: {
    'image': base64Image,
  });

  // Handle the API response
  if (response.statusCode == 200) {
    // Success
  } else {
    // Error
  }
}

In this example, the apiUrl parameter is the URL of the API endpoint, and the imagePath parameter is the path to the image file on the device.

Eames answered 14/2, 2023 at 12:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.