How to send multipart file with Flutter 2023
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
Table of Contents
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
- Codeplayon Jetpack Compose Tutorial
- Codeplayon Android Tutorial
- Codeplayon Flutter Tutorial
- Codeplayon on Github