Flutter how to send multiple files to http post - dart

I'd like to send two files to http post
curl looks like this
curl -X POST "https://api-us.faceplusplus.com/facepp/v3/compare" \
-F "api_key=<api_key>" \
-F "api_secret=<api_secret>" \
-F "image_file1 =file1" \
-F "image_file1 =file2"
I tried like this.
File first;
File second;
var uri = Uri.parse('https://api-us.faceplusplus.com/facepp/v3/compare');
var request = new http.MultipartRequest("POST", uri);
request.fields['api_key'] = apiKey;
request.fields['api_secret'] = apiSecret;
request.files.add(await http.MultipartFile.fromPath('image_file1', first.path, contentType: new MediaType('application', 'x-tar')));
request.files.add(await http.MultipartFile.fromPath('image_file2', second.path, contentType: new MediaType('application', 'x-tar')));
var response = await request.send();
print(response);
But it returns this
NoSuchMethodError: Class 'String' has no instance getter 'path'.
How can I send these properly?

It doesn't look like first and second are actually Files. When they are definitely files, as in the following example, I get 401 (as expected, as I have a dummy api key).
main() async {
File first = File('pubspec.yaml');
File second = File('analysis_options.yaml');
Uri uri = Uri.parse('https://api-us.faceplusplus.com/facepp/v3/compare');
http.MultipartRequest request = new http.MultipartRequest('POST', uri);
request.fields['api_key'] = 'apiKey';
request.fields['api_secret'] = 'apiSecret';
request.files.add(await http.MultipartFile.fromPath('image_file1', first.path,
contentType: new MediaType('application', 'x-tar')));
request.files.add(await http.MultipartFile.fromPath(
'image_file2', second.path,
contentType: new MediaType('application', 'x-tar')));
http.StreamedResponse response = await request.send();
print(response.statusCode);
}

import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:path/path.dart';
class Post {
String title = '';
String description = '';
List<File> files = [];
Future<http.StreamedResponse> sendFiles() async {
try {
var uri = Uri.parse('https://example.com/api-endpoint');
var request = http.MultipartRequest('POST', uri);
// Headers
request.headers.addAll({
'Accept': 'application/json',
'Authorization': 'Bearer $token',
});
// Fields
request.fields['title'] = title;
request.fields['description'] = description;
// Files
await Future.forEach(
files,
(file) async => {
request.files.add(
http.MultipartFile(
'files',
(http.ByteStream(file.openRead())).cast(),
await file.length(),
filename: basename(file.path),
),
)
},
);
return await request.send();
} catch (err) {
print(err);
return null;
}
}
}

You can try with Flutter DIO Package
https://pub.dev/packages/dio
import 'package:dio/dio.dart';
// Create a Dio instance
final Dio dio = Dio();
// Set up the request options
Options options = Options(
method: 'POST',
);
// Create a FormData instance to hold the files you want to upload
FormData formData = FormData();
// Add the files to the FormData instance
formData.files.addAll([
MapEntry('file1', await MultipartFile.fromFile(file1Path)),
MapEntry('file2', await MultipartFile.fromFile(file2Path)),
// Add more files here if you want
]);
try {
// Send the POST request
Response response = await dio.post(
url,
data: formData,
options: options,
);
// Do something with the response
print(response.data);
} catch (e) {
// show my error
log(e);
}

Related

image uploading failing using dio package

I am trying to upload an image in flutter using Dio package but its failing. I need to send an image in formdata.
API >> needs request body as imageUpload:image
Code for image upload
static Future uploadProfilePicToS3(File imageFile) async {
try {
FormData formData = new FormData.from(
{'imageUpload': new UploadFileInfo(imageFile, "profile_pic.jpg")});
var response =
await Dio().post(UPLOAD_PROFILE_PIC, data: {'imageUpload': formData});
print(response.statusCode);
} catch (error) {
throw (error);
}
}
Error >>>
E/flutter ( 4025): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)]
Unhandled Exception: DioError [DioErrorType.DEFAULT]: Converting
object to an encodable object failed: Instance of 'UploadFileInfo'#0
Let me know if there is any other way.
I used dio for post a file path with some other information in this way :
Dio dio = new Dio();
FormData formData = new FormData();
formData.add(
"apiKey",
"my_api_key",
);
formData.add(
"file",
"image_path",
);
Response response = await dio.post(
"https://localhost",
data: formData,
onSendProgress: (int sent, int total) {
// do something
},
).catchError((onError) {
throw Exception('something');
});
use this code
Future<ImageProperty> uploadImage(File imageFile, processfunction) async {
final StringBuffer url = new StringBuffer(BASE_URL + "/wp-json/wp/v2/media");
Dio dio = new Dio();
var token = await _getToken();
try {
FormData formData = FormData.fromMap(
{"file": await MultipartFile.fromFile(imageFile.path)},
);
print(url);
if (token != null) {
dio.options.headers["Authorization"] = "Bearer $token";
print(dio.options.headers);
}
var response = await dio.post(
url.toString(),
data: formData,
onSendProgress: processfunction,
);
print(response.data);
return Future.value(response.data);
} on DioError catch (e) {
print(e);
}
}

download attachments from mail using microsoft graph rest api

I've been successfully getting the list of mails in inbox using microsoft graph rest api but i'm having tough time to understand documentation on how to download attachments from mail.
For example : This question stackoverflow answer speaks about what i intend to achieve but i don't understand what is message_id in the endpoint mentioned : https://outlook.office.com/api/v2.0/me/messages/{message_id}/attachments
UPDATE
i was able to get the details of attachment using following endpoint : https://graph.microsoft.com/v1.0/me/messages/{id}/attachments and got the following response.
I was under an impression that response would probably contain link to download the attachment, however the response contains key called contentBytes which i guess is the encrypted content of file.
For attachment resource of file type contentBytes property returns
base64-encoded contents of the file
Example
The following Node.js example demonstrates how to get attachment properties along with attachment content (there is a dependency to request library):
const attachment = await getAttachment(
userId,
mesasageId,
attachmentId,
accessToken
);
const fileContent = new Buffer(attachment.contentBytes, 'base64');
//...
where
const requestAsync = options => {
return new Promise((resolve, reject) => {
request(options, (error, res, body) => {
if (!error && res.statusCode == 200) {
resolve(body);
} else {
reject(error);
}
});
});
};
const getAttachment = (userId, messageId, attachmentId, accessToken) => {
return requestAsync({
url: `https://graph.microsoft.com/v1.0/users/${userId}/messages/${messageId}/attachments/${attachmentId}`,
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json;odata.metadata=none"
}
}).then(data => {
return JSON.parse(data);
});
};
Update
The following example demonstrates how to download attachment as a file in a browser
try {
const attachment = await getAttachment(
userId,
mesasageId,
attachmentId,
accessToken
);
download("data:application/pdf;base64," + attachment.contentBytes, "Sample.pdf","application/pdf");
} catch (ex) {
console.log(ex);
}
where
async function getAttachment(userId, messageId, attachmentId, accessToken){
const res = await fetch(
`https://graph.microsoft.com/v1.0/users/${userId}/messages/${messageId}/attachments/${attachmentId}`,
{
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json;odata.metadata=none"
}
}
);
return res.json();
}
Dependency: download.js library
I don't know if this would help but you just have to add /$value at the end of your request :
https://graph.microsoft.com/v1.0/me/messages/{message_id}/attachments/{attachment_id}/$value

Flutter how to post json array

How to post below json array?
"LstUserOptions": [
{
"OptionID": "ca339e40-10cc-4459-b9ec-07f7df0f4c69"
}
]
i found the solution :
List<Map> carOptionJson = new List();
CarJson carJson = new CarJson("ca339e40-10cc-4459-b9ec-07f7df0f4c69");
carOptionJson.add(carJson.TojsonData());
var body = json.encode({
"LstUserOptions": carOptionJson
});
http.Response response = await http.post(
Uri.encodeFull(ConfigApi.SAVE),
body: body,
headers: {'Content-type': 'application/json'});
class CarJson {
String OptionID;
CarJson(this.OptionID);
Map<String, dynamic> TojsonData() {
var map = new Map<String, dynamic>();
map["OptionID"] = OptionID;
return map;
}
}
how to done this work with dio package i send whole my data with dio and now i want send a array of json with it , is correct this code if assume my json array is body
FormData formData = new FormData.from({
"cars": body
});
response = await dio.post("url", data:
formData);

Post request with Cookies in Flutter

I'm trying to add Cookies to my request:
Here i get csrftoken with a GET request:
Future<String> getCsrftoken() async{
var response = await http.get(Uri.encodeFull('http://test/accounts/login/'));
var csrftoken = response.headers.remove('set-cookie').substring(10,74); //csrf
64 chars
return csrftoken;
}
Here i'm trying to perform the POST (application/x-www-form-urlencoded) request using the package Dio.
getSessionId() async {
var csrf = await getCsrftoken();
var cj = new CookieJar();
List<Cookie> cookies = [new Cookie("csrftoken", csrf)];
cj.saveFromResponse(Uri.parse("http://test/accounts/login/"), cookies);
List<Cookie> results = cj.loadForRequest(Uri.parse("http://test/accounts/login/"));
var dio = new Dio(new Options(
baseUrl: "http://test/accounts/login/",
connectTimeout: 5000,
receiveTimeout: 100000,
// 5s
headers: {
},
contentType: ContentType.JSON,
// Transform the response data to a String encoded with UTF8.
// The default value is [ResponseType.JSON].
responseType: ResponseType.PLAIN
));
Response<String> response;
response = await dio.post("",
data: {
"username": "username",
"password": "password",
"csrfmiddlewaretoken" : getCsrftoken()
},
// Send data with "application/x-www-form-urlencoded" format
options: new Options(
contentType: ContentType.parse("application/x-www-form-urlencoded")),
);
print(response.statusCode);
}
I get 403 status code, because i need to add as a cookie csrftoken.
How should I proceed?
From the Dio Dart API Docs:
Cookie Manager
You can manage the request/response cookies using cookieJar .
The dio cookie manage API is based on the withdrawn cookie_jar.
You can create a CookieJar or PersistCookieJar to manage cookies automatically, and dio use the CookieJar by default, which saves the cookies in RAM. If you want to persists cookies, you can use the PersistCookieJar class, the example codes as follows:
var dio = new Dio();
dio.cookieJar=new PersistCookieJar("./cookies");
PersistCookieJar is a cookie manager which implements the standard cookie policy declared in RFC. PersistCookieJar persists the cookies in files, so if the application exit, the cookies always exist unless call delete explicitly.
More details about cookie_jar see : https://github.com/flutterchina/cookie_jar .
Check if the csrftoken needs to be passed in the header and the cookie or just one of them. It sometimes needs to be included as a header, which is shown in the example below, but the header name varies. To persist cookies, use a PersistCookieJar. Other options are persisted through BaseOptions (previously named Options).
Add to pubspec.yaml the latest versions of these plugins
path_provider: ^1.1.0
dio: ^2.1.6
cookie_jar: ^1.0.0
In a new class named webFunctions:
import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
class webFunctions {
final Dio _dio = Dio();
PersistCookieJar persistentCookies;
final String URL = "http://test/";
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<Directory> get _localCoookieDirectory async {
final path = await _localPath;
final Directory dir = new Directory('$path/cookies');
await dir.create();
return dir;
}
Future<String> getCsrftoken() async{
try {
String csrfTokenValue;
final Directory dir = await _localCoookieDirectory;
final cookiePath = dir.path;
persistentCookies = new PersistCookieJar(dir: '$cookiePath');
persistentCookies.deleteAll(); //clearing any existing cookies for a fresh start
_dio.interceptors.add(
CookieManager(persistentCookies) //this sets up _dio to persist cookies throughout subsequent requests
);
_dio.options = new BaseOptions(
baseUrl: URL,
contentType: ContentType.json,
responseType: ResponseType.plain,
connectTimeout: 5000,
receiveTimeout: 100000,
headers: {
HttpHeaders.userAgentHeader: "dio",
"Connection": "keep-alive",
},
); //BaseOptions will be persisted throughout subsequent requests made with _dio
_dio.interceptors.add(
InterceptorsWrapper(
onResponse:(Response response) {
List<Cookie> cookies = persistentCookies.loadForRequest(Uri.parse(URL));
csrfTokenValue = cookies.firstWhere((c) => c.name == 'csrftoken', orElse: () => null)?.value;
if (csrfTokenValue != null) {
_dio.options.headers['X-CSRF-TOKEN'] = csrfTokenValue; //setting the csrftoken from the response in the headers
}
return response;
}
)
);
await _dio.get("/accounts/login/");
return csrfTokenValue;
} catch (error, stacktrace) {
print("Exception occured: $error stackTrace: $stacktrace");
return null;
}
}
getSessionId() async {
try {
final csrf = await getCsrftoken();
FormData formData = new FormData.from({
"username": "username",
"password": 'A *passphrase* is stronger than a password.',
"csrfmiddlewaretoken" : '$csrf'
});
Options optionData = new Options(
contentType: ContentType.parse("application/x-www-form-urlencoded"),
);
Response response = await _dio.post("/accounts/login/", data: formData, options: optionData);
print(response.statusCode);
} on DioError catch(e) {
if(e.response != null) {
print( e.response.statusCode.toString() + " " + e.response.statusMessage);
print(e.response.data);
print(e.response.headers);
print(e.response.request);
} else{
print(e.request);
print(e.message);
}
}
catch (error, stacktrace) {
print("Exception occured: $error stackTrace: $stacktrace");
return null;
}
}
}

How do I dynamically add a file input to FormData in Dart?

I am trying to use the FormData class to send data to my server with HttpRequest.send(). I need to do a POST request with multiple fields. It should work the same as this Javascript code:
//Upload File
var uploadFile = function(file, tag, callback)
{
var xhr = new XMLHttpRequest();
xhr.open('POST', "upload/", true);
xhr.onreadystatechange=function()
{
if (xhr.readyState==4 && xhr.status==200)
{
callback();
}
}
var formData = new FormData();
formData.append('file', file);
formData.append('tag', tag);
var csrftoken = $.cookie('csrftoken');
xhr.setRequestHeader("X-CSRFToken", csrftoken);
xhr.send(formData);
};
But FormData doesn't seem to work the same way in Dart. Could someone explain how to do this in Dart, if it is possible?
Unfortunately this looks to be a bug. I've opened issue http://code.google.com/p/dart/issues/detail?id=7152 to track. Thanks for the use case.
You have to use FormData.appendBlob :
void uploadFile(File file, String tag, callback) {
final xhr = new HttpRequest();
xhr.open('POST', "upload/", true);
xhr.on.readyStateChange.add((e) {
if (xhr.readyState == 4 && xhr.status == 200) {
callback();
}
});
final formData = new FormData();
formData.appendBlob('file', file);
formData.append('tag', tag);
xhr.send(formData);
};

Resources