I'm working on a Flutter app where I'm trying to integrate an API to add restaurant items, including an image upload. The image upload works perfectly when tested with Postman, but it fails to upload the image from my Flutter app.
Here is the code I'm using in my Flutter app:
static Future<ApiGenericResponse> addRestaurantItem({
required String itemNameOrArabicName,
required String itemDescriptionOrArabicDescription,
required double price,
required File? image,
required bool isArabic,
required String status,
}) async {
final Map<String, dynamic> data = {
if (isArabic)
'item_arabic_name': itemNameOrArabicName
else
'item_name': itemNameOrArabicName,
if (isArabic)
'item_arabic_description': itemDescriptionOrArabicDescription
else
'item_description': itemDescriptionOrArabicDescription,
'price': price,
'status': status == LocaleKeys.active.tr() ? 1 : 0,
};
if (image != null) {
data['image'] = await MultipartFile.fromFile(
image.path,
);
}
final form = await FormData.fromMap(data);
try {
final response = await ApiHelper(apiService).callApi(
endpoint: 'add-restaurant-item',
requestType: RequestType.post,
formData: form);
if (response.success) {
return ApiGenericResponse(
success: true, data: response.data, message: response.message);
} else {
return ApiGenericResponse(success: false, message: response.message);
}
} catch (e) {
return ApiGenericResponse(success: false, message: e.toString());
}
}
In my backend logs, I see that the payload is received without the image:
[2024-07-25 07:30:19] local.INFO: array (
'item_name' => 'Log test',
'item_description' => 'log',
'price' => '11.0',
'status' => '0',
'lang' => 'en',
)
Additional Information:
I have ensured that the Content-Type header is set to multipart/form-data. I have tried running the app on both an emulator and a physical device, but the issue persists. The image is accessible and its path is correctly passed to the MultipartFile.fromFile method.
I was using dio package. For some reason, dio's Multipart isn't uploading image to the server which is weird. When I tried calling the same api with http package, image upload worked. Here's my http api call code:
static Future<ApiGenericResponse> addRestaurantItemHttp({
required String itemNameOrArabicName,
required String itemDescriptionOrArabicDescription,
required double price,
required File? image,
required bool isArabic,
required String status,
}) async {
var uri = Uri.parse('https://test6.accrualdev.com/api/add- restaurant- item');
var request = http.MultipartRequest('POST', uri);
// Adding fields to the request
request.fields.addAll({
if (isArabic)
'item_arabic_name': itemNameOrArabicName
else
'item_name': itemNameOrArabicName,
if (isArabic)
'item_arabic_description': itemDescriptionOrArabicDescription
else
'item_description': itemDescriptionOrArabicDescription,
'price': price.toString(),
'status': status == LocaleKeys.active.tr() ? '1' : '0',
'lang': isArabic ? 'en' : 'ar'
});
// Adding the image file if it exists
if (image != null) {
request.files.add(await http.MultipartFile.fromPath(
'image',
image.path,
));
}
final String? accessToken = SessionManager.instance.accessToken;
request.headers.addAll({
'Authorization': 'Bearer $accessToken',
});
try {
// Sending the request
var streamedResponse = await request.send();
// Getting the response
var response = await http.Response.fromStream(streamedResponse);
// Checking the status code
if (response.statusCode == 200) {
var responseData = json.decode(response.body);
if (responseData["status"] == true) {
return ApiGenericResponse(
success: true,
data: responseData['data'],
message: responseData['msg'],
);
} else
return ApiGenericResponse(
success: false, message: responseData["error"]);
} else {
var errorData = json.decode(response.body);
return ApiGenericResponse(
success: false,
message: errorData['error'] ?? 'Unknown error occurred',
);
}
} catch (e) {
return ApiGenericResponse(
success: false,
message: e.toString(),
);
}
}