Flutter Tutorial

How to send multipart file with Flutter 2023

How to send multipart file with Flutter

How to send multipart file with Flutter. Hi Everyone in this article I am sharing code on how to update a profile in the flutter App. Like in your app have a profile screen and you can update your profile with image and details like first name, last name, profile image, etc.

In this example, I am using HTTP multipart post request.  flutter http post form data example send the image into flutter multipart request.

flutter image upload to server from camera and gallery

You can only send string, int, and list data types using http.post() with flutter. How can you send files/videos/images to the server? MultipartRequest is the best way to send images/videos/files to the server.

What is a Multi-Part Post Request?

The body of a POST Request is usually composed of textual key/value pairs. You can include binary content files (images, documents, etc.) in a multipart POST Request. In addition to regular text values, you can also include binary content.

Flutter’s HTTP Library allows you to make multi-part POST requests

This section will focus on creating a function that can send a file to a URL using a multipart POST request.

Next, we will discuss how to create an app that allows the user to enter the URL to send the request and pick an image to send to the server. The status of the request is returned.

How to send multipart file with Flutter API Example

Let’s Start to create an example with the image upload form gallery. Here I am creating a profile screen and using the updated profile details. Let’s Create a flutter project and add the below dependency.

Step 1:-  Add dependencies in your pubspec.yaml file and get pub.

dependencies:
  flutter:
    sdk: flutter
  intl: ^0.18.0
  http: ^0.13.5
  image_picker: ^0.8.2

Step:-  2  Add API endPoint in your ApiClient class.

class ApiClient {
  static final String BASE_URL = "https://codeplayon.com/v1/";
  static String UpdateProfile = BASE_URL + "/users/profileUpdate";
 
}

Step:- 3 Pick an Image from the gallery.

void _pickImage() async {
  try {
    final pickedFile = await _picker.getImage(source: ImageSource.gallery);
    setState(() {
      _imageFile = pickedFile!;
      PickimagePath = File(pickedFile!.path);
      print("Image picker error " + pickedFile!.path);
    });
  } catch (e) {
    print("Image picker error " + e.toString());
  }
}

 

 

Step:- 4 Update Profile API call Method.

Future<void> UpdateProfile1() async {
  try {
    EasyLoading.show();
    String token = Prefs.getString(TYPE.S_TOKEN.toString());
    int id = Prefs.getInt(TYPE.S_USER_ID.toString());
    var request = http.MultipartRequest(
        'POST', Uri.parse(ApiClient.UpdateProfile));
    request.headers.addAll(
      {"Authorization": "Bearer $token"},
    );
    if(_imageFile.path==""){

    }else{
      request.files.add(await http.MultipartFile.fromPath("file",_imageFile.path));
    }

    request.fields['id'] = id.toString();
    request.fields['f_Name'] = name;
    request.fields['m_Name'] = "";
    request.fields['l_Name'] = lastName;
    request.fields['name'] = name + lastName;
    request.fields['email'] = email;
    request.fields['mobile'] = phone;
    request.fields['address1'] = Address;
    request.fields['PIN'] = ZipCode;
    request.fields['city_id'] = CityId.toString();
    request.fields['country_id'] = CounrtyId.toString();
    print("request Update profile : ${request}");
    var response = await request.send();
    var response1 = await http.Response.fromStream(response);
    if (response.statusCode == 200) {
      EasyLoading.dismiss();
      print("Response Update profile : ${response1.body}");
      final parsedJson = jsonDecode(response1.body);
      showToastMessage(parsedJson["message"]);
      Navigator.pop(context);
      // do something...
    } else {
      print("Response Update profile :${response1.body} " );
      EasyLoading.dismiss();
      // do something...
    }
  } catch (e) {
    print("error ${e.toString()}");
    EasyLoading.dismiss();
  }
}

 

Complete the code of the Update Profile dart file.

import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.dart';
import 'package:ev_charging/Screens/Custom/BorderBox.dart';
import 'package:ev_charging/Utils/constants.dart';
import 'package:ev_charging/Utils/widget_functions.dart';
import 'package:http/http.dart' as http;
import '../../Models/Country.dart';
import '../../Models/ProfileDetailsResponse.dart';
import '../../Redux/Store/Store.dart';
import '../../Utils/SharedPreferenceService.dart';
import '../../retrofit/APIClient.dart';
import '../../retrofit/ApiService.dart';

class UserProfileEditView extends StatefulWidget {
  ProfileDetailsResponse profiledetails;
  LoadCountryData CountryList;
  List<dynamic> State ;

   UserProfileEditView({Key? key,required this.profiledetails,required this.CountryList,required this.State}) : super(key: key);

  @override
  _UserProfileEditViewState createState() => _UserProfileEditViewState();
}

class _UserProfileEditViewState extends State<UserProfileEditView> {
  bool isShowPass = false;
  bool isEditModeEnable = true;
  String name= "";
  String lastName= "";
  String email="";
  String phone = "";
  int CounrtyId =0;
  String CountryName="";
  String Statename="";
  int CityId =0;
  String ImageUrl="";
  String Address = "";
  String ZipCode="";
  late PickedFile _imageFile = new PickedFile("");
  late File PickimagePath= new File("");
  final ImagePicker _picker = ImagePicker();



  @override
  void initState() {
    // TODO: implement initState
    Prefs.init();
    if(widget.profiledetails.data.isEmpty){

    }else{
      name = widget.profiledetails.data[0].f_Name;
      lastName = widget.profiledetails.data[0].l_Name;
      email = widget.profiledetails.data[0].email;
      phone = widget.profiledetails.data[0].mobile;
      CounrtyId = widget.profiledetails.data[0].country_id;
      CityId = widget.profiledetails.data[0].city_id;
      Address = widget.profiledetails.data[0].address1;

      ImageUrl = widget.profiledetails.data[0].image_url;
      if(widget.profiledetails.data[0].PIN==0){
        ZipCode = "";
      }else{
        ZipCode = widget.profiledetails.data[0].PIN.toString();
      }
      try {
        var C_List = widget.CountryList.data.firstWhere((e) => e.id == widget.profiledetails.data[0].country_id);
        Country country = C_List;
        CountryName = country.name;
        var S_list = widget.State.firstWhere((e) => e["id"] == widget.profiledetails.data[0].state_id);
        print("StateName:- "+S_list["name"]);
        Statename = S_list["name"];
      }catch(e){

      }


    }
    super.initState();
  }
  Widget _ImageView() {
    if (PickimagePath.path == "") {
      return CircleAvatar(
        radius: 60.0,
        backgroundImage: NetworkImage(( widget.profiledetails.data.length>0)?  widget.profiledetails.data[0].image_url:""),
      );
    } else {
      return CircleAvatar(
        radius: 60.0,
        backgroundImage: FileImage(PickimagePath),
      );
    }
  }


  @override
  Widget build(BuildContext context) {
  
    final Size size = MediaQuery.of(context).size;
    final ThemeData themeData = Theme.of(context);

    const padding = 25.0;

    return GestureDetector(
      onTap: () {
        FocusScope.of(context).unfocus();
      },
      child: Scaffold(
        backgroundColor: COLOR_BACKGROUND,
        body: Container(
          padding: EdgeInsets.fromLTRB(16, 62, 16, 0),
          width: size.width,
          height: size.height,
          // color: COLOR_WHITE,
          child: SingleChildScrollView(
            scrollDirection: Axis.vertical,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Container(
                  child: Column(children: [
                    Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          BorderBox(
                            child: Icon(Icons.arrow_back_ios_new),
                            width: 44,
                            height: 44,
                            isAction: 1,
                            tabHandler: () {
                              Navigator.pop(context);
                            },
                          ),
                          Column(
                            children: [
                              _ImageView(),
                              TextButton(
                                onPressed: (() {
                                  _pickImage();
                                }),
                                child: Text(
                                  "Add Photo",
                                  style: TextStyle(
                                      color: isEditModeEnable
                                          ? COLOR_GRAY
                                          : COLOR_THEME,
                                      fontWeight: FontWeight.w400,
                                      fontSize: fontsize14),
                                ),
                              ),
                            ],
                          ),
                          Container(
                            child: Column(
                              children: [
                                BorderBox(
                                  child: Icon(
                                    Icons.edit,
                                    color: COLOR_GRAY,
                                  ),
                                  width: 44,
                                  height: 44,
                                  isAction: 1,
                                  tabHandler: () {
                                    isEditModeEnable = !isEditModeEnable;
                                  },
                                ),
                                Text(
                                  "Edit",
                                  style: TextStyle(
                                      color: isEditModeEnable
                                          ? COLOR_GRAY
                                          : COLOR_THEME,
                                      fontWeight: FontWeight.w400,
                                      fontSize: fontsize14),
                                ),
                              ],
                            ),
                          ),
                        ]),
                    TextField(
                      onChanged: (text) {
                          name = text.trim();
                      },
                      textAlignVertical: TextAlignVertical.center,
                      style: themeData.textTheme.bodyText2,
                      controller: TextEditingController(text: name)..selection = TextSelection.collapsed(offset: name.length),
                      decoration: InputDecoration(
                        // hintStyle: TextStyle(color: COLOR_THEME),
                        hintText: "First name",
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: COLOR_GRAY),
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.02),
                    TextField(
                      onChanged: (text) {
                       lastName = text;
                      },
                      textAlignVertical: TextAlignVertical.center,
                      style: themeData.textTheme.bodyText2,
                      controller: TextEditingController(text: lastName)..selection = TextSelection.collapsed(offset: lastName.length),
                      decoration: InputDecoration(
                        // hintStyle: TextStyle(color: COLOR_THEME),
                        hintText: "Last name",
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: COLOR_GRAY),
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.02),
                    TextField(
                      onChanged: (text) {
                          email = text.trim();
                      },
                      textAlignVertical: TextAlignVertical.center,
                      style: themeData.textTheme.bodyText2,
                      controller: TextEditingController(text: email)..selection = TextSelection.collapsed(offset: email.length),
                      decoration: InputDecoration(
                        // hintStyle: TextStyle(color: COLOR_THEME),
                        hintText: "Email",
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: COLOR_GRAY),
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.02),
                    TextField(
                      onChanged: (text) {
                          phone = text.trim();
                      },
                      textAlignVertical: TextAlignVertical.center,
                      style: themeData.textTheme.bodyText2,
                      controller: TextEditingController(text: phone)..selection = TextSelection.collapsed(offset: phone.length),
                      decoration: InputDecoration(
                        // hintStyle: TextStyle(color: COLOR_THEME),
                        hintText: "Phone",
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: COLOR_GRAY),
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.02),
                    TextField(
                      readOnly: true,
                      onTap: () {
                        FocusScope.of(context).requestFocus(new FocusNode());
                       
                      },
                      onChanged: (text) {},
                      textAlignVertical: TextAlignVertical.center,
                      style: themeData.textTheme.bodyText2,
                      autocorrect: false,
                      enableSuggestions: false,
                      controller: TextEditingController(text: CountryName),
                      decoration: InputDecoration(
                        // hintStyle: TextStyle(color: COLOR_THEME),
                        hintText: "Country",
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: COLOR_GRAY),
                        ),
                        suffixIcon: IconButton(
                          icon: Icon(
                            isShowPass
                                ? Icons.keyboard_arrow_up
                                : Icons.keyboard_arrow_down,
                            color: Colors.grey,
                          ),
                          onPressed: () {
                            setState(() {
                              isShowPass = !isShowPass;
                            });
                          },
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.02),
                    TextField(
                      onTap: () {
                        FocusScope.of(context).requestFocus(new FocusNode());
                       
                      },
                      textAlignVertical: TextAlignVertical.center,
                      style: themeData.textTheme.bodyText2,
                      autocorrect: false,
                      enableSuggestions: false,
                      controller: TextEditingController(text: Statename),
                      decoration: InputDecoration(
                        // hintStyle: TextStyle(color: COLOR_THEME),
                        hintText: "State",
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: COLOR_GRAY),
                        ),
                        suffixIcon: IconButton(
                          icon: Icon(
                            isShowPass
                                ? Icons.keyboard_arrow_up
                                : Icons.keyboard_arrow_down,
                            color: Colors.grey,
                          ),
                          onPressed: () {
                            setState(() {
                              isShowPass = !isShowPass;
                            });
                          },
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.02),
                    TextField(
                      onChanged: (text) {
                          Address = text.trim();
                      },
                      textAlignVertical: TextAlignVertical.center,
                      style: themeData.textTheme.bodyText2,
                      controller: TextEditingController(text: Address)..selection = TextSelection.collapsed(offset: Address.length),
                      decoration: InputDecoration(
                        // hintStyle: TextStyle(color: COLOR_THEME),
                        hintText: "Address",
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: COLOR_GRAY),
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.02),
                    TextField(
                      onChanged: (text) {
                        ZipCode = text;
                      },
                      textAlignVertical: TextAlignVertical.center,
                      style: themeData.textTheme.bodyText2,
                      controller: TextEditingController(text: ZipCode)..selection = TextSelection.collapsed(offset: ZipCode.length),
                      decoration: InputDecoration(
                        // hintStyle: TextStyle(color: COLOR_THEME),
                        hintText: "Zip code",
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: COLOR_GRAY),
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.02),
                    TextButton(
                      onPressed: () {
                        // UpdateProfile();
                        UpdateProfile1();
                      },
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Text(
                            "Submit",
                            style: themeData.textTheme.headline6,
                          ),
                        ],
                      ),
                      style: ButtonStyle(
                        padding: MaterialStateProperty.all<EdgeInsets>(
                            EdgeInsets.fromLTRB(70, 18, 70, 18)),
                        backgroundColor:
                            MaterialStateProperty.all<Color>(COLOR_THEME),
                        foregroundColor:
                            MaterialStateProperty.all<Color>(Colors.white),
                        shape:
                            MaterialStateProperty.all<RoundedRectangleBorder>(
                          RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(12.0),
                          ),
                        ),
                      ),
                    ),
                    addVarticalSpace(size.height * 0.04),
                  ]),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  void _pickImage() async {
    try {
      final pickedFile = await _picker.getImage(source: ImageSource.gallery);
      setState(() {
        _imageFile = pickedFile!;
        PickimagePath = File(pickedFile!.path);
        print("Image picker error " + pickedFile!.path);
      });
    } catch (e) {
      print("Image picker error " + e.toString());
    }
  }

    Future<void> UpdateProfile1() async {
      try {
        EasyLoading.show();
        String token = Prefs.getString(TYPE.S_TOKEN.toString());
        int id = Prefs.getInt(TYPE.S_USER_ID.toString());
        var request = http.MultipartRequest(
            'POST', Uri.parse(ApiClient.UpdateProfile));
        request.headers.addAll(
          {"Authorization": "Bearer $token"},
        );
        if(_imageFile.path==""){

        }else{
          request.files.add(await http.MultipartFile.fromPath("file",_imageFile.path));
        }

        request.fields['id'] = id.toString();
        request.fields['f_Name'] = name;
        request.fields['m_Name'] = "";
        request.fields['l_Name'] = lastName;
        request.fields['name'] = name + lastName;
        request.fields['email'] = email;
        request.fields['mobile'] = phone;
        request.fields['address1'] = Address;
        request.fields['PIN'] = ZipCode;
        request.fields['city_id'] = CityId.toString();
        request.fields['country_id'] = CounrtyId.toString();
        print("request Update profile : ${request}");
        var response = await request.send();
        var response1 = await http.Response.fromStream(response);
        if (response.statusCode == 200) {
          EasyLoading.dismiss();
          print("Response Update profile : ${response1.body}");
          final parsedJson = jsonDecode(response1.body);
          showToastMessage(parsedJson["message"]);
          Navigator.pop(context);
          // do something...
        } else {
          print("Response Update profile :${response1.body} " );
          EasyLoading.dismiss();
          // do something...
        }
      } catch (e) {
        print("error ${e.toString()}");
        EasyLoading.dismiss();
      }
    }
}

Read More Tutorial