flutterdartmultipartform-dataimagepicker

Save picture in asset folder from android emulator and post it to API


I'm a beginner in Flutter, I have a picture in the android emulator gallery, and I'm trying to update my user's profile picture through an API.

My API function : this is the way I'm updating it (by the way, the phone field is getting updated, and the image is not) I'm receiving a status code of 200

Future<Provider> updateProviderInfo(Provider person) async {

 person.idUser = await FlutterSession().get("id");
final response = await http.put(
  Uri.parse(ApiConstants.BASE_URL + ApiConstants.UPDATE_PROVIDER),
  headers: <String, String>{
    'Content-Type': 'application/json; charset=UTF-8',
  },
  body: jsonEncode(<String, String>{
    'providerId': person.idUser.toString(),
    'providerProfilePicture': person.providerProfilePicture,
    'phone' :"92211130030"
  }),
);
if (response.statusCode == 200) {
  // If the server did return a 200 OK response,
  // then parse the JSON.
  Fluttertoast.showToast(
      msg: "Updated with success",
      toastLength: Toast.LENGTH_SHORT,
      gravity: ToastGravity.CENTER,
      timeInSecForIosWeb: 1,
      backgroundColor: Colors.blue,
      textColor: Colors.white,
      fontSize: 16.0);
  return Provider.fromJson(jsonDecode(response.body));
} else {
  // If the server did not return a 200 OK response,
  // then throw an exception.
  throw Exception('Failed to update User Type :Service Provider.');
}}

How I'm loading my image:

This is the way I'm getting the Image from the emulator's Gallery or camera :

 Future<File> _loadImage(ImageSource imageSource) async {

PickedFile file = await _imagePicker.getImage(source: imageSource,imageQuality: 50, // <- Reduce Image quality
    maxHeight: 250,  // <- reduce the image size
    maxWidth: 250);
File mFile;

if (null != file) {
  Directory directory = await getTemporaryDirectory();
  //mFile = await _saveImageToDisk(file.path, directory);
  Map map = Map();
  map['path'] = file.path;
  String myLastFilePath = file.path.substring(file.path.indexOf("picker"));
  print ("my try : "+myLastFilePath);

  provider.providerProfilePicture = myLastFilePath;
  print("my path :  "+provider.providerProfilePicture);
  map['directory'] = directory;
  mFile = await compute(_saveImageToDisk, map);
}
return mFile; }

This is what my view looks like

I'm receiving a 200 status code and the phone number is getting updated, but the image field in DB is empty

my Route API test in postman

I think I should use a multiPartFormData, but I have no idea how to use it, and I'm not sure any guidance will be appreciated thank you


Solution

  • Below is the code for using a multiPart request:

    static Future<bool> uploadFile(File file) async {
      // open a byteStream
      var stream = http.ByteStream(file.openRead());
      stream.cast();
    
      // get file length
      var length = await file.length();
    
      Uri uri = Uri.parse(ApiConstants.BASE_URL + ApiConstants.UPDATE_PROVIDER);
    
      // create multipart request
      var request = http.MultipartRequest("POST", uri);
    
      // multipart that takes file
      var multipartFile = http.MultipartFile(
        'file',
        stream,
        length,
        filename: basename(file.path),
      );
    
      // add file to multipart
      request.files.add(multipartFile);
    
      // send
      var response = await request.send();
      // print(response.statusCode);
      if (response.statusCode == 200) {
        ...
      } else {
        ...
      }
    }
    

    Update this code according to your needs and see if it works. You might need to modify your server-side code a little bit to make it work properly.