DioError [DioErrorType.RESPONSE]: Http status error [404] - flutter

Postman form-data request
Request body containing
Expected Response body
Dio Flutter code
import 'package:dio/dio.dart';
import 'package:flutter_project/config/config.dart';
import '../model/postImage.dart';
import 'dart:io';
Future<PostImage> postImage(File image) async{
String fileName = image.path.split('/').last;
print(fileName);
try{
Dio dio = new Dio();
FormData formData = FormData.fromMap({
"file": await MultipartFile.fromFile(image.path,filename: fileName)
});
Map<String, String> headers= <String,String>{
'Content-Type':'multipart/form-data'
};
print("${baseURL}files/upload");
Response response = await dio.post("${baseURL}files/upload",data: formData);
if(response.statusCode == 200){
print("Uploaded");
}
else{
print(response.data);
}
}
catch(e){
print(e);
}
}
Expection that I am getting : DioError [DioErrorType.RESPONSE]: Http status error [404]

I added contentType: new MediaType("image", "jpeg")//in the formData. It works now.
Full Code :
import 'package:dio/dio.dart';
import 'package:flutter_project/config/config.dart';
import '../model/postImage.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
Future<PostImage> postImage(File image) async {
String fileName = image.path.split('/').last;
print(fileName);
try {
Dio dio = new Dio();
FormData formData = FormData.fromMap({
"file": await MultipartFile.fromFile(
image.path,
filename: fileName,
contentType: new MediaType("image", "jpeg"),
)
});
Map<String, String> headers = <String, String>{
'Content-Type': 'multipart/form-data'
};
print("${baseURL}files/upload");
Response response =
await dio.post("${baseURL}files/upload", data: formData);
if (response.statusCode == 200) {
print("Uploaded");
} else {
print(response.data);
}
print('Out');
} catch (e) {
print(e);
}
}

When I encountered an HTTP 4xx error while using Dio and I was sure I had my Authorization set, what I did to make it work is to set the Options() parameter explicitly. Precisely, I set the method type (for a get request) and authorisation token like this: Dio().get(url, options: Options(method: "GET", headers: { "Authorization": "Bearer ${LocalStorage().getString(Keys.token)}", })));.
You can also set content-type if need be. To make it easier, you can simply copy-paste into the headers: argument, some of the header values set in/by your postman when you make the same request using postman.

Related

how to send a File to an REST api [duplicate]

I use a web service for image processing , it works well in Postman:
Now I want to make http request in flutter with Dart:
import 'package:http/http.dart' as http;
static ocr(File image) async {
var url = '${API_URL}ocr';
var bytes = image.readAsBytesSync();
var response = await http.post(
url,
headers:{ "Content-Type":"multipart/form-data" } ,
body: { "lang":"fas" , "image":bytes},
encoding: Encoding.getByName("utf-8")
);
return response.body;
}
but I don't know how to upload the image file, in above code I get exception: Bad state: Cannot set the body fields of a Request with content-type "multipart/form-data".
How should I write the body of request?
Your workaround should work; many servers will accept application/x-www-form-urlencoded as an alternative (although data is encoded moderately inefficiently).
However, it is possible to use dart:http to do this. Instead of using http.post, you'll want to use a http.MultipartFile object.
From the dart documentation:
var request = new http.MultipartRequest("POST", url);
request.fields['user'] = 'someone#somewhere.com';
request.files.add(http.MultipartFile.fromPath(
'package',
'build/package.tar.gz',
contentType: new MediaType('application', 'x-tar'),
));
request.send().then((response) {
if (response.statusCode == 200) print("Uploaded!");
});
I'd like to recommend dio package to you , dio is a powerful Http client for Dart/Flutter, which supports Interceptors, FormData, Request Cancellation, File Downloading, Timeout etc.
dio is very easy to use, in this case you can:
Sending FormData:
FormData formData = new FormData.from({
"name": "wendux",
"file1": new UploadFileInfo(new File("./upload.jpg"), "upload1.jpg")
});
response = await dio.post("/info", data: formData)
More details please refer to dio。
This can be achieved using the MultipartRequest class (https://pub.dev/documentation/http/latest/http/MultipartRequest-class.html)
Change the media type and uri as needed.
uploadFile() async {
var postUri = Uri.parse("<APIUrl>");
var request = new http.MultipartRequest("POST", postUri);
request.fields['user'] = 'blah';
request.files.add(new http.MultipartFile.fromBytes('file', await File.fromUri("<path/to/file>").readAsBytes(), contentType: new MediaType('image', 'jpeg')))
request.send().then((response) {
if (response.statusCode == 200) print("Uploaded!");
});
}
I found a working example without using any external plugin , this only uses
import 'package:http/http.dart' as http;
import 'dart:io';
import 'package:path/path.dart';
import 'package:async/async.dart';
import 'dart:convert';
Code
var stream =
new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
// get file length
var length = await imageFile.length(); //imageFile is your image file
Map<String, String> headers = {
"Accept": "application/json",
"Authorization": "Bearer " + token
}; // ignore this headers if there is no authentication
// string to uri
var uri = Uri.parse(Constants.BASE_URL + "api endpoint here");
// create multipart request
var request = new http.MultipartRequest("POST", uri);
// multipart that takes file
var multipartFileSign = new http.MultipartFile('profile_pic', stream, length,
filename: basename(imageFile.path));
// add file to multipart
request.files.add(multipartFileSign);
//add headers
request.headers.addAll(headers);
//adding params
request.fields['loginId'] = '12';
request.fields['firstName'] = 'abc';
// request.fields['lastName'] = 'efg';
// send
var response = await request.send();
print(response.statusCode);
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
How to upload image file using restAPI in flutter/dart.
This work for me.
var postUri = Uri.parse("apiUrl");
http.MultipartRequest request = new http.MultipartRequest("POST", postUri);
http.MultipartFile multipartFile = await http.MultipartFile.fromPath(
'file', filePath);
request.files.add(multipartFile);
http.StreamedResponse response = await request.send();
print(response.statusCode);
Updated 2021 way:
using flutter http and mime
import 'package:mime/mime.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import 'dart:io';
Future<dynamic> multipartImageUpload(String baseUrl, String api, File image) async {
var uri = Uri.parse(baseUrl + api);
final mimeTypeData =
lookupMimeType(image.path, headerBytes: [0xFF, 0xD8]).split('/');
// Intilize the multipart request
final imageUploadRequest = http.MultipartRequest('PUT', uri);
// Attach the file in the request
final file = await http.MultipartFile.fromPath('image', image.path,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
imageUploadRequest.files.add(file);
// add headers if needed
//imageUploadRequest.headers.addAll(<some-headers>);
try {
final streamedResponse = await imageUploadRequest.send();
final response = await http.Response.fromStream(streamedResponse);
return response;
} catch (e) {
print(e);
return null;
}
}
Use MultipartRequest class.
How to upload image file using restAPI in flutter/dart
void uploadImage1(File _image) async {
// open a byteStream
var stream = new http.ByteStream(DelegatingStream.typed(_image.openRead()));
// get file length
var length = await _image.length();
// string to uri
var uri = Uri.parse("enter here upload URL");
// create multipart request
var request = new http.MultipartRequest("POST", uri);
// if you need more parameters to parse, add those like this. i added "user_id". here this "user_id" is a key of the API request
request.fields["user_id"] = "text";
// multipart that takes file.. here this "image_file" is a key of the API request
var multipartFile = new http.MultipartFile('image_file', stream, length, filename: basename(_image.path));
// add file to multipart
request.files.add(multipartFile);
// send request to upload image
await request.send().then((response) async {
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}).catchError((e) {
print(e);
});
}
name spaces:
import 'package:path/path.dart';
import 'package:async/async.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
UPLOAD IMAGE TO SERVER WITH FORM DATA
To upload image to server you need a dio library.
Features:
Authorization (adding token)
Adding extra field like: username, etc
Adding Image to upload
Code example:
import 'package:dio/dio.dart' as dio;
import 'dart:convert';
try {
///[1] CREATING INSTANCE
var dioRequest = dio.Dio();
dioRequest.options.baseUrl = '<YOUR-URL>';
//[2] ADDING TOKEN
dioRequest.options.headers = {
'Authorization': '<IF-YOU-NEED-ADD-TOKEN-HERE>',
'Content-Type': 'application/x-www-form-urlencoded'
};
//[3] ADDING EXTRA INFO
var formData =
new dio.FormData.fromMap({'<SOME-EXTRA-FIELD>': 'username-forexample'});
//[4] ADD IMAGE TO UPLOAD
var file = await dio.MultipartFile.fromFile(image.path,
filename: basename(image.path),
contentType: MediaType("image", basename(image.path)));
formData.files.add(MapEntry('photo', file));
//[5] SEND TO SERVER
var response = await dioRequest.post(
url,
data: formData,
);
final result = json.decode(response.toString())['result'];
} catch (err) {
print('ERROR $err');
}
To add a header and use http multipart with https://pub.dev/packages/multi_image_picker Plugin,
This is the code.
var request = http.MultipartRequest(
'POST', Uri.parse(myurl)
);
//Header....
request.headers['Authorization'] ='bearer $authorizationToken';
request.fields['PropertyName'] = propertyName;
request.fields['Country'] = country.toString();
request.fields['Description'] = des;
request.fields['State'] = state.toString();
request.files.add(http.MultipartFile.fromBytes(
'ImagePaths',
learnImage,
filename: 'some-file-name.jpg',
contentType: MediaType("image", "jpg"),
)
);
var response = await request.send();
print(response.stream);
print(response.statusCode);
final res = await http.Response.fromStream(response);
print(res.body);
To use HTTP and https://pub.dev/packages/image_picker PLUGIN
This is the code
var request = http.MultipartRequest(
'POST', Uri.parse(myurl)
);
request.headers['Authorization'] ='bearer $authorizationToken';
request.fields['PropertyName'] = propertyName;
request.fields['Country'] = country.toString();
request.fields['Description'] = des;
request.fields['State'] = state.toString();
request.files.add(await http.MultipartFile.fromPath(
'ImagePaths',
file.path
)
);
var response = await request.send();
print(response.stream);
print(response.statusCode);
final res = await http.Response.fromStream(response);
print(res.body);
Working Code
String path = userSelectedImagePath;
Map<String, String> data = {
"name": firstName!,
"email": userEmail!
};
String token = await LocaldbHelper().getToken();
Map<String, String> headers = {
'X-Requested-With': 'XMLHttpRequest',
'authorization': 'Bearer $token',
};
var request = http.MultipartRequest(
'POST',
Uri.parse(ApiUrl.updateProfile),
);
request.fields.addAll(data);
request.headers.addAll(headers);
var multipartFile = await http.MultipartFile.fromPath(
'avatar', path); //returns a Future<MultipartFile>
request.files.add(multipartFile);
http.StreamedResponse response = await request.send();
final respStr = await response.stream.bytesToString();
var jsonData = jsonDecode(respStr);
if (response.statusCode == 200) {
// success
} else {
// error
}
Just leaving this here, if anyone is trying to upload a pdf or any other document using MultipartRequest method.
Just add the content type as -
contentType: new MediaType('application', 'pdf')
Good code with Dio and FilePicker for post file on your server. I use flutter for the web.
FilePicker
Dio
First you need writing Dio post method.
Future postImportClient(PlatformFile file) async {
try {
var urlBase = 'your url';
var mfile = MultipartFile.fromBytes(file.bytes!, filename: file.name);
var formData = FormData();
formData.files.add(MapEntry('file', mfile));
await _dio.post(urlBase, data: formData);
} on DioError catch (error) {
throw Exception(error);
}
}
Initial FilePicker and get file.
FilePickerResult? result = await FilePickerWeb.platform.pickFiles();
if (result != null) {
var file = result.files.single;
await client.postImportClient(file);
}
Good luck!
create FormData:
final formDataMap = <String, dynamic>{};
formDataMap["stringKey"] = "string";
List<MultipartFile> multipartImageList = [];
await Future.forEach(imagePaths as List<String>,(String path) async {
final multiPartFile = await MultipartFile.fromFile(
path,
contentType: MediaType("image", "jpeg"),
);
multipartImageList.add(multiPartFile);
});
formDataMap["image[]"] = multipartImageList;
final formData = FormData.fromMap(formDataMap);
With Retrofit & Dio:
#MultiPart()
#POST("{{url}}")
Future<dynamic> uploadFormData(
#Body() FormData formData,
);
With Hearder
upload image
Future uploadImageMedia(File fileImage, String token) async {
final mimeTypeData =
lookupMimeType(fileImage.path, headerBytes: [0xFF, 0xD8]).split('/');
final imageUploadRequest =
http.MultipartRequest('POST', Uri.parse(mainUrlSite + "wp-json/wp/v2/media"));
final file = await http.MultipartFile.fromPath('file', fileImage.path,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
imageUploadRequest.files.add(file);
imageUploadRequest.headers.addAll({
"Authorization": "Bearer " + token
});
try {
final streamedResponse = await imageUploadRequest.send();
streamedResponse.stream.transform(utf8.decoder).listen((value) {
print(value);
return Future.value(value);
});
} catch (e) {
print(e);
}
}
I use Dio library with put method:
var formData = FormData.fromMap({
'simpleParam': 'example',
'file': await MultipartFile.fromFile(filePath, filename: 'file.jpg')
});
var dio = Dio();
dio.options.headers[HttpHeaders.authorizationHeader] = myToken;
var response = new Response(); //Response from Dio
response = await dio.put(myUrl + "/myApi", data: formData);
The result is in response.data
try {
result[HttpKeys.status] = false;
var request = http.MultipartRequest('POST', url);
request.fields.addAll(body);
if (avatar.path.isNotEmpty) {
request.files.add(await http.MultipartFile.fromPath('uploadedImg', avatar.path));
}
request.headers.addAll(headers);
http.StreamedResponse streamResponse = await request.send();
final response = await http.Response.fromStream(streamResponse);
if (response.statusCode == 200) {
var resMap = jsonDecode(response.body);
debugPrint('<== 𝕊𝕚𝕘𝕟 𝕦𝕡 𝕤𝕦𝕔𝕔𝕖𝕤𝕤𝕗𝕦𝕝𝕝𝕪 ==>');
// debugPrint(response.body);
result[HttpKeys.status] = true;
result[HttpKeys.message] = resMap[HttpKeys.message];
result[HttpKeys.data] = resMap['data'];
return result;
} else {
var resMap = jsonDecode(response.body);
result[HttpKeys.message] = resMap[HttpKeys.message];
return result;
}
} catch (error) {
result[HttpKeys.message] = error.toString();
return result;
}
With dio I do like this:
Future<void> _uploadFileAsFormData(String path) async {
try {
final dio = Dio();
dio.options.headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
final file =
await MultipartFile.fromFile(path, filename: 'test_file');
final formData = FormData.fromMap({'file': file}); // 'file' - this is an api key, can be different
final response = await dio.put( // or dio.post
uploadFileUrlAsString,
data: formData,
);
} catch (err) {
print('uploading error: $err');
}
}

how to use flutter dio connect-type multipart?

my code here
Dio dio = new Dio();
String fileName = event.file!.path.split('/').last;
FormData formData = FormData.fromMap({
"file":
await MultipartFile.fromFile(event.file!.path, filename: fileName),
});
try {
var response = await dio.post(
"url",
data: formData,
options: new Options(
contentType: "multipart/form-data",
headers: {
"token": await getToken(),
// "Content-Type": "multipart/form-data"
}),
// headers: {"token": "test:1234"}),
);
}
catch (e){
print(e);
}
my error version 1
error type. DioErrorType.other
error : SocketException : OS Error Connection refused,errorno=61
and
my error version 2
error type. DioErrorType.response
error : Http status error[400]
my requestOptions here
method = "POST"
_defaultContentType = "multipart/form-data"
How can I hand over the file to the server? The problem I think is that the content-type is not suitable, so there seems to be an error.
I have a similar implementation. I also use Dio, though in my code, I have it abstracted away with _api.
Future<Response> uploadLogo({#required File file}) async {
String fileName = file.path.split('/').last;
FormData formData = FormData.fromMap({"file": await MultipartFile.fromFile(file.path, filename:fileName) });
return await _api.post(url: url, data: formData);
}
Note that I don't even set the content type. I suspect that Dio looks at the type of object in the data parameter, and handles the appropriate headers/encoding under the hood.
Also, if you have having the content-type set to something unexpected, I'd recommend checking if you are using any RequestInterceptor's. I was, and had to write an exception, because I was setting it correctectly, by my RequestInterceptor was overriding it, (because all of my other endpoints wanted JSON):
class RequestInterceptor extends InterceptorsWrapper {
#override
void onRequest(RequestOptions options, handler) {
if(!options.headers.containsKey('content-type')) {
options.headers['content-type'] = 'application/json';
}
// ...
super.onRequest(options, handler);
}
}

Is there something wrong with the way [Flutter Web] sends a request POST message to the API server?

The open api request I'm trying to use requires an image binary value with content-type of multipart/form-data format.
I know you can't use dart:io in flutter web. I tried to upload an image in multipart/form-data format to the api server in flutter web while looking at several posts.
However, only a message appeared stating that the image could not be recognized.
This is the last thing I tried to create multipart types in flutter web.
import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
PlatformFile? objFile;
pickImage() async {
var result = await FilePicker.platform.pickFiles(
withReadStream: true,
);
setState(() {
objFile = result!.files.single;
});
uploadImage();
}
uploadImage() async {
FormData formData = FormData.fromMap({'image' : MultipartFile(test!, objFile!.size, filename: objFile!.name)});
Dio dio = new Dio();
var response = await dio.post('API url', data: formData);
}
I additionally used Multipart.form Bytes from http , Multipart.form Bytes from dio . But the result was the same.
The value checked by the request body through the postman interceptor.
content-type=multipart/form-data;bounary=--dio-boundary-1105759322
----dio-boundary-1105759322
content-disposition: form-data; name="image"; filename="test.jpeg"
content-type: application/octet-stream
ÿØÿÛC
%# , #&')*)-0-(0%()(ÿÛC
(((((((((((((((((((((((((((((((((((((((((((((((((((ÿÀŽv"ÿÄÿÄC!1AQaq"‘2¡±#BÁÑR3CðñSbr’á‚Â$&4c“ÿÄÿÄ&!1A2Q"a3BRÿÚ?ù× „É<$/cŸt8D`aú¦Ä#bálŒZVM„ٔʓTL›eOò¢“
èKÇ(p¢‰¥C’ÄÙ‚Ñx²Ù1Jcœ)B›¢$ ¢‚&
‚7› ˜Žp”{&ÊÀÁAî¤Æ
‚nÈ CØÃêOýÒ›§á$sÊ‚r¡ìLÂ…;"éMI½î«gæV<æ6οÙ%_ƒY®}7Òû€¯MŒ&g¹å|µ£ëÐúc\tÚƵƈúÕ]#kQ‹D/Ÿú·cu9«Hà/¢lÚ–êè·¼&Þt
¯H‚&ɶìÛà®iƒh²SöãÔTs[l›/?[s(’˜¨o€¤Û‹*¥AÖ”ðbUgYR’!äJ!M‹™‹«›î©aÉ*ᕨ4p SÉ…¤)‰ì§=‘âJ» oÙGDRåÌy0—²û r ò€·²?Te8±KSTR8ŹDAååþ7)Oˆk)õ²Qk#Ù€Œ ?DÜû&Ä›„ÍÅ”lQjð¡NÑ%HTWP˜²wýÒc(Ÿð¤ð¢S<*6º>ÊaCœ „Ù0
^J(ª%¢ƒFPm‘^u4^èM‘åL…##•0Qÿ ºi…32§ÙC•D¿&Èw’ˆº‘Ü"…”<&ýРwP {p ¸DCd¼&ÿ©#¨ˆ› La~¨p¦„)’÷‚ˆº²æÒ›ªĘ̀Šaá€0‹n <ò¦M“YM„ L«=ÕnæÊlªŽÂƒóc„m‚—È™Uó ªºäªÛ•F†\…}7?¨ªZL`*£è¾ŽÝÌ1¤ÜBúk6­
---------------------------SKIP------------------------------
PTiMÂ!¢(èÊ€YÊÂœ"ÑÂ_T<Ñ5îPp™ð ¨„ôOˤ?¢z\ÂÚ¡½ÐiÊc쨟ÝHŸ¢“3ÝA˜( ‘ÊH›(l€Å¼)Ä‘rEÈ[€‹¬”¼x
W7q?ΣHt®“§¤y\½Ìÿ:ÿÍtÖ§T°AÊÕ\ËZVƒÔPha30%1*¶›Ž!7è¥|f›„îÕQ±„9N6åW,¨^Ù8PHN./Ê€îª2ß*{(l¡™šOU¢Ôå3œ*ꜨŠ‹“3¼$«B*ÌŒS„+EÒ‘Ý VHpV±`²³ó€µgܪ‚#“Ü)À!NPCƒÝIÅԛ–”xý”²™# ?U‚‹n€å!Œ¦&é*ƒ™¨wÄÖØY¢>«}&ü¢×\Ý?ó*9ç%Òº˜#çò H€¥&ꃒ¤(
‚0O8##EÎéÊœ#TÕr‚ºT¹ÈÔ7T“2¢ƒœbÅsuOî¶Ô0>‹ŸT|Gô•Óa®ïšÔÇe¤T
he<,¨[ü¶[…·M#ZOˆjtˤÝE© QÿÙ
----dio-boundary-1105759322--
When I use the MultipartFile.fromFile method used in flutter ios, I got the response normally. So I'm pretty sure there must be some mistake or misinformation in the flutter web setup.
Thanks in advance!
this is how I managed to upload an image to Laravel backend using Flutter Web
import 'dart:io';
import 'package:dio/dio.dart' as dio;
import 'package:file_picker/file_picker.dart';
Future pickupUserImage2() async {
PlatformFile? objFile;
var picked = await FilePicker.platform.pickFiles();
objFile = picked!.files.single;
String? apiUrl = Get.find<MainController>().apiUrl;
String url = '';
if (apiUrl != null) url = apiUrl + 'images';
List<int> list;
list = List<int>.from(objFile.bytes!);
dio.FormData formData = dio.FormData.fromMap({'file': dio.MultipartFile.fromBytes(list, filename: objFile.name)});
DioNetworking _dio = new DioNetworking();
dynamic result = await _dio.postData(
url,
formData,
contentType: 'multipart/form-data',
);
if (result['status'] == true) {
showToast(result['message']);
return ImageModel.Image.fromJson(result['data']);
}
}
I added a file using MultipartFile.fromBytes which has the first parameter as List which I created from this method "List.from(objFile.bytes!);"
Notes :
ImageModel.Image is a model I created to handle the image result
DioNetworking is a class that perform dio requests , I just created it to do the
authentication stuff
import 'package:dio/dio.dart';
class DioNetworking {
Dio _dio = new Dio();
Future postData(
String url,
dynamic data, {
String? contentType,
}) async {
try {
Response response = await _dio.post(url,
data: data,
options: Options(headers: {
'content-type': contentType != null ? contentType : 'application/json',
'Accept': 'application/json',
// 'Authorization': 'Bearer ${token ?? ''}'
// other headers
}));
if (response.statusCode == 200) {
dynamic data = response.data;
return data;
} else {
print(response.statusCode);
}
} on DioError catch (e) {
print(e);
if (e.type == DioErrorType.connectTimeout) {
return {'status': 'Connect Timed Out'};
}
if (e.type == DioErrorType.receiveTimeout) {
return {'status': 'Receive Timed Out'};
}
if (e.type == DioErrorType.response) {
print(e.response!.data);
print(e.response!.headers);
}
}
}
}

How to make API call in flutter with header key?

Suppose the host site is: :
https://dev.xyz.com
API header key: "x-api-key: 7462-3172-8773-3312-5819"
To register a new user you have to call PUT method: {{host}}/api/customer/
And the body is like this:
{"email": "test#example.net",
"password": "aabbccdd",
"Name": "John",
}
Now how do I accomplish this in flutter? I have searched through several tutorials and still in confusion.
Import the http package from dart library and alias it as http, reason for this aliasing is that you dont want to have .get() method suggestion everywhere in the file. So when you use it with http as http.get() it will give you suggestion for get, In which you can pass the parameter called headers.
Code goes as follows:
import 'package:http/http.dart' as http;
url = 'YOUR_URL';
var response = await http.get(
url,
headers: {HttpHeaders.authorizationHeader: TOKEN}, //an example header
);
In your case,
import 'dart:convert';
import 'dart:io';
import 'dart:async';
main() async {
String url =
'https://dev.xyz.com';
Map map = {
'data': {'apikey': '7462-3172-8773-3312-5819'},
};
print(await apiRequest(url, map));
}
Future<String> apiRequest(String url, Map jsonMap) async {
HttpClient httpClient = new HttpClient();
HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(jsonMap)));
HttpClientResponse response = await request.close();
// todo - you should check the response.statusCode
String reply = await response.transform(utf8.decoder).join();
httpClient.close();
return reply;
}
You need put the header on the http request. For example:
await put(urlApi + 'update/'+ customer.id, headers: {'token': token, 'content-type': 'application/json'},body: body);

How to upload images and file to a server in Flutter?

I use a web service for image processing , it works well in Postman:
Now I want to make http request in flutter with Dart:
import 'package:http/http.dart' as http;
static ocr(File image) async {
var url = '${API_URL}ocr';
var bytes = image.readAsBytesSync();
var response = await http.post(
url,
headers:{ "Content-Type":"multipart/form-data" } ,
body: { "lang":"fas" , "image":bytes},
encoding: Encoding.getByName("utf-8")
);
return response.body;
}
but I don't know how to upload the image file, in above code I get exception: Bad state: Cannot set the body fields of a Request with content-type "multipart/form-data".
How should I write the body of request?
Your workaround should work; many servers will accept application/x-www-form-urlencoded as an alternative (although data is encoded moderately inefficiently).
However, it is possible to use dart:http to do this. Instead of using http.post, you'll want to use a http.MultipartFile object.
From the dart documentation:
var request = new http.MultipartRequest("POST", url);
request.fields['user'] = 'someone#somewhere.com';
request.files.add(http.MultipartFile.fromPath(
'package',
'build/package.tar.gz',
contentType: new MediaType('application', 'x-tar'),
));
request.send().then((response) {
if (response.statusCode == 200) print("Uploaded!");
});
I'd like to recommend dio package to you , dio is a powerful Http client for Dart/Flutter, which supports Interceptors, FormData, Request Cancellation, File Downloading, Timeout etc.
dio is very easy to use, in this case you can:
Sending FormData:
FormData formData = new FormData.from({
"name": "wendux",
"file1": new UploadFileInfo(new File("./upload.jpg"), "upload1.jpg")
});
response = await dio.post("/info", data: formData)
More details please refer to dio。
This can be achieved using the MultipartRequest class (https://pub.dev/documentation/http/latest/http/MultipartRequest-class.html)
Change the media type and uri as needed.
uploadFile() async {
var postUri = Uri.parse("<APIUrl>");
var request = new http.MultipartRequest("POST", postUri);
request.fields['user'] = 'blah';
request.files.add(new http.MultipartFile.fromBytes('file', await File.fromUri("<path/to/file>").readAsBytes(), contentType: new MediaType('image', 'jpeg')))
request.send().then((response) {
if (response.statusCode == 200) print("Uploaded!");
});
}
I found a working example without using any external plugin , this only uses
import 'package:http/http.dart' as http;
import 'dart:io';
import 'package:path/path.dart';
import 'package:async/async.dart';
import 'dart:convert';
Code
var stream =
new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
// get file length
var length = await imageFile.length(); //imageFile is your image file
Map<String, String> headers = {
"Accept": "application/json",
"Authorization": "Bearer " + token
}; // ignore this headers if there is no authentication
// string to uri
var uri = Uri.parse(Constants.BASE_URL + "api endpoint here");
// create multipart request
var request = new http.MultipartRequest("POST", uri);
// multipart that takes file
var multipartFileSign = new http.MultipartFile('profile_pic', stream, length,
filename: basename(imageFile.path));
// add file to multipart
request.files.add(multipartFileSign);
//add headers
request.headers.addAll(headers);
//adding params
request.fields['loginId'] = '12';
request.fields['firstName'] = 'abc';
// request.fields['lastName'] = 'efg';
// send
var response = await request.send();
print(response.statusCode);
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
How to upload image file using restAPI in flutter/dart.
This work for me.
var postUri = Uri.parse("apiUrl");
http.MultipartRequest request = new http.MultipartRequest("POST", postUri);
http.MultipartFile multipartFile = await http.MultipartFile.fromPath(
'file', filePath);
request.files.add(multipartFile);
http.StreamedResponse response = await request.send();
print(response.statusCode);
Updated 2021 way:
using flutter http and mime
import 'package:mime/mime.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import 'dart:io';
Future<dynamic> multipartImageUpload(String baseUrl, String api, File image) async {
var uri = Uri.parse(baseUrl + api);
final mimeTypeData =
lookupMimeType(image.path, headerBytes: [0xFF, 0xD8]).split('/');
// Intilize the multipart request
final imageUploadRequest = http.MultipartRequest('PUT', uri);
// Attach the file in the request
final file = await http.MultipartFile.fromPath('image', image.path,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
imageUploadRequest.files.add(file);
// add headers if needed
//imageUploadRequest.headers.addAll(<some-headers>);
try {
final streamedResponse = await imageUploadRequest.send();
final response = await http.Response.fromStream(streamedResponse);
return response;
} catch (e) {
print(e);
return null;
}
}
Use MultipartRequest class.
How to upload image file using restAPI in flutter/dart
void uploadImage1(File _image) async {
// open a byteStream
var stream = new http.ByteStream(DelegatingStream.typed(_image.openRead()));
// get file length
var length = await _image.length();
// string to uri
var uri = Uri.parse("enter here upload URL");
// create multipart request
var request = new http.MultipartRequest("POST", uri);
// if you need more parameters to parse, add those like this. i added "user_id". here this "user_id" is a key of the API request
request.fields["user_id"] = "text";
// multipart that takes file.. here this "image_file" is a key of the API request
var multipartFile = new http.MultipartFile('image_file', stream, length, filename: basename(_image.path));
// add file to multipart
request.files.add(multipartFile);
// send request to upload image
await request.send().then((response) async {
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}).catchError((e) {
print(e);
});
}
name spaces:
import 'package:path/path.dart';
import 'package:async/async.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
UPLOAD IMAGE TO SERVER WITH FORM DATA
To upload image to server you need a dio library.
Features:
Authorization (adding token)
Adding extra field like: username, etc
Adding Image to upload
Code example:
import 'package:dio/dio.dart' as dio;
import 'dart:convert';
try {
///[1] CREATING INSTANCE
var dioRequest = dio.Dio();
dioRequest.options.baseUrl = '<YOUR-URL>';
//[2] ADDING TOKEN
dioRequest.options.headers = {
'Authorization': '<IF-YOU-NEED-ADD-TOKEN-HERE>',
'Content-Type': 'application/x-www-form-urlencoded'
};
//[3] ADDING EXTRA INFO
var formData =
new dio.FormData.fromMap({'<SOME-EXTRA-FIELD>': 'username-forexample'});
//[4] ADD IMAGE TO UPLOAD
var file = await dio.MultipartFile.fromFile(image.path,
filename: basename(image.path),
contentType: MediaType("image", basename(image.path)));
formData.files.add(MapEntry('photo', file));
//[5] SEND TO SERVER
var response = await dioRequest.post(
url,
data: formData,
);
final result = json.decode(response.toString())['result'];
} catch (err) {
print('ERROR $err');
}
To add a header and use http multipart with https://pub.dev/packages/multi_image_picker Plugin,
This is the code.
var request = http.MultipartRequest(
'POST', Uri.parse(myurl)
);
//Header....
request.headers['Authorization'] ='bearer $authorizationToken';
request.fields['PropertyName'] = propertyName;
request.fields['Country'] = country.toString();
request.fields['Description'] = des;
request.fields['State'] = state.toString();
request.files.add(http.MultipartFile.fromBytes(
'ImagePaths',
learnImage,
filename: 'some-file-name.jpg',
contentType: MediaType("image", "jpg"),
)
);
var response = await request.send();
print(response.stream);
print(response.statusCode);
final res = await http.Response.fromStream(response);
print(res.body);
To use HTTP and https://pub.dev/packages/image_picker PLUGIN
This is the code
var request = http.MultipartRequest(
'POST', Uri.parse(myurl)
);
request.headers['Authorization'] ='bearer $authorizationToken';
request.fields['PropertyName'] = propertyName;
request.fields['Country'] = country.toString();
request.fields['Description'] = des;
request.fields['State'] = state.toString();
request.files.add(await http.MultipartFile.fromPath(
'ImagePaths',
file.path
)
);
var response = await request.send();
print(response.stream);
print(response.statusCode);
final res = await http.Response.fromStream(response);
print(res.body);
Working Code
String path = userSelectedImagePath;
Map<String, String> data = {
"name": firstName!,
"email": userEmail!
};
String token = await LocaldbHelper().getToken();
Map<String, String> headers = {
'X-Requested-With': 'XMLHttpRequest',
'authorization': 'Bearer $token',
};
var request = http.MultipartRequest(
'POST',
Uri.parse(ApiUrl.updateProfile),
);
request.fields.addAll(data);
request.headers.addAll(headers);
var multipartFile = await http.MultipartFile.fromPath(
'avatar', path); //returns a Future<MultipartFile>
request.files.add(multipartFile);
http.StreamedResponse response = await request.send();
final respStr = await response.stream.bytesToString();
var jsonData = jsonDecode(respStr);
if (response.statusCode == 200) {
// success
} else {
// error
}
Just leaving this here, if anyone is trying to upload a pdf or any other document using MultipartRequest method.
Just add the content type as -
contentType: new MediaType('application', 'pdf')
Good code with Dio and FilePicker for post file on your server. I use flutter for the web.
FilePicker
Dio
First you need writing Dio post method.
Future postImportClient(PlatformFile file) async {
try {
var urlBase = 'your url';
var mfile = MultipartFile.fromBytes(file.bytes!, filename: file.name);
var formData = FormData();
formData.files.add(MapEntry('file', mfile));
await _dio.post(urlBase, data: formData);
} on DioError catch (error) {
throw Exception(error);
}
}
Initial FilePicker and get file.
FilePickerResult? result = await FilePickerWeb.platform.pickFiles();
if (result != null) {
var file = result.files.single;
await client.postImportClient(file);
}
Good luck!
create FormData:
final formDataMap = <String, dynamic>{};
formDataMap["stringKey"] = "string";
List<MultipartFile> multipartImageList = [];
await Future.forEach(imagePaths as List<String>,(String path) async {
final multiPartFile = await MultipartFile.fromFile(
path,
contentType: MediaType("image", "jpeg"),
);
multipartImageList.add(multiPartFile);
});
formDataMap["image[]"] = multipartImageList;
final formData = FormData.fromMap(formDataMap);
With Retrofit & Dio:
#MultiPart()
#POST("{{url}}")
Future<dynamic> uploadFormData(
#Body() FormData formData,
);
With Hearder
upload image
Future uploadImageMedia(File fileImage, String token) async {
final mimeTypeData =
lookupMimeType(fileImage.path, headerBytes: [0xFF, 0xD8]).split('/');
final imageUploadRequest =
http.MultipartRequest('POST', Uri.parse(mainUrlSite + "wp-json/wp/v2/media"));
final file = await http.MultipartFile.fromPath('file', fileImage.path,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
imageUploadRequest.files.add(file);
imageUploadRequest.headers.addAll({
"Authorization": "Bearer " + token
});
try {
final streamedResponse = await imageUploadRequest.send();
streamedResponse.stream.transform(utf8.decoder).listen((value) {
print(value);
return Future.value(value);
});
} catch (e) {
print(e);
}
}
I use Dio library with put method:
var formData = FormData.fromMap({
'simpleParam': 'example',
'file': await MultipartFile.fromFile(filePath, filename: 'file.jpg')
});
var dio = Dio();
dio.options.headers[HttpHeaders.authorizationHeader] = myToken;
var response = new Response(); //Response from Dio
response = await dio.put(myUrl + "/myApi", data: formData);
The result is in response.data
try {
result[HttpKeys.status] = false;
var request = http.MultipartRequest('POST', url);
request.fields.addAll(body);
if (avatar.path.isNotEmpty) {
request.files.add(await http.MultipartFile.fromPath('uploadedImg', avatar.path));
}
request.headers.addAll(headers);
http.StreamedResponse streamResponse = await request.send();
final response = await http.Response.fromStream(streamResponse);
if (response.statusCode == 200) {
var resMap = jsonDecode(response.body);
debugPrint('<== 𝕊𝕚𝕘𝕟 𝕦𝕡 𝕤𝕦𝕔𝕔𝕖𝕤𝕤𝕗𝕦𝕝𝕝𝕪 ==>');
// debugPrint(response.body);
result[HttpKeys.status] = true;
result[HttpKeys.message] = resMap[HttpKeys.message];
result[HttpKeys.data] = resMap['data'];
return result;
} else {
var resMap = jsonDecode(response.body);
result[HttpKeys.message] = resMap[HttpKeys.message];
return result;
}
} catch (error) {
result[HttpKeys.message] = error.toString();
return result;
}
Here is the code where I am passing Image, route which may be like '/register', and data which is Map<String, String> like data={'directory':'profile'}.
For Uploading Image to Laravel API, Authorization in header is compulsory otherwise it would return "You don't have permission to access this resource". I am passing token as EMPTY string like String token='' as I am uploading
Image at user registration time
This Authorization for read and write is defined in domainurl/public/.htaccess file, you can change it
Try to understand the below code and all the issue would be resolve.
Future uploadImage({
required XFile file,
required String route,
required Map<String, String> data,
}) async {
String url = API_Url + route;
final uri = Uri.parse(url);
try {
http.MultipartRequest request = http.MultipartRequest("POST", uri);
http.MultipartFile multipartFile =
await http.MultipartFile.fromPath('image', file.path);
request.files.add(multipartFile);
request.headers.addAll(_header());
request.fields.addAll(data);
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
print(jsonDecode(response.body));
return jsonDecode(response.body);
} catch (e) {
return null;
}
}
_header() {
return {"Content-Type": "multipart/form-data",
'Authorization': 'Bearer ${token}',
};
}
With dio I do like this:
Future<void> _uploadFileAsFormData(String path) async {
try {
final dio = Dio();
dio.options.headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
final file =
await MultipartFile.fromFile(path, filename: 'test_file');
final formData = FormData.fromMap({'file': file}); // 'file' - this is an api key, can be different
final response = await dio.put( // or dio.post
uploadFileUrlAsString,
data: formData,
);
} catch (err) {
print('uploading error: $err');
}
}