I have response.header in header. I want to pass that header to another response.
so, my approach is to save the header in shared preference and then retrieve it.
final prefs = await SharedPreferences.getInstance();
prefs.setString('header', response.headers.toString());
and then retrieve it
final prefs = await SharedPreferences.getInstance();
String? head = prefs.getString('header');
Map<String, String> authHeaders = jsonDecode(head!);
but authHeders is giving me an error.
Unhandled Exception: FormatException: Unexpected character (at character 2)
header before saving to SharedPreferences.
{connection: keep-alive, set-cookie: XSRF-TOKEN=nBYdTZyY2FrQUl0RitDemxmdnNVMVRacC9XcENyV3pJankiLCJtYWMiOiJkOTRmZWMwYjYyMDdjMjAwNjBmZTJmZDYyNGYzYzI0YTVjMDNmN2VjZjc3MzZkM2UzNzc1MTk2ZjViOGE0MGMyIiwidGFnIjoiIn0%3D; expires=Mon, 01-Aug-2022 08:56:00 GMT; Max-Age=7200; path=/; samesite=lax,laravel_session=eyJpdiI6Iko1U1ZkejhNWVo3b0twb0pwdS9QMVE9PSIsInZhbHVlIjoiVUxyTFVmMm9XSG95VHd6cGxCVThqSExvSzJQWmQ2WWRMRGpoT0xsVjExdHl1M0xnZ2xGZjd2WDRVdHRqa1J4TU4rRjByakFoSUNHT2lPTGVUb0Z4aHNhWjRleTM0TnBjakRPRzc4WkZVWDMvTzdqNlpoVTBCRWRsOTlwcHIvNFQiLCJtYWMiOiI0MTRhMjRkNGY3Njg0ZDI4NjU1MzFmZjI2M2FkOTA5NDc4ZWJhYzhiZTA5MTFkZTQ2ZmJlY2UxNzBlZjc3MTc3IiwidGFnIjoiIn0%3D; path=/; httponly; samesite=lax, cache-control: no-cache, private, date: Mon, 01 Aug 2022 06:56:00 GMT, vary: Accept-Encoding, content-encoding: gzip, cf-cache-status: DYNAMIC, report-to: {"endpoint .......
header after retrieving it.
{connection: keep-alive, set-cookie: XSRF-TOKEN=nBYdTZyY2FrQUl0RitDemxmdnNVMVRacC9XcENyV3pJankiLCJtYWMiOiJkOTRmZWMwYjYyMDdjMjAwNjBmZTJmZDYyNGYzYzI0YTVjMDNmN2VjZjc3MzZkM2UzNzc1MTk2ZjViOGE0MGMyIiwidGFnIjoiIn0%3D; expires=Mon, 01-Aug-2022 08:56:00 GMT; Max-Age=7200; path=/; samesite=lax,laravel_session=eyJpdiI6Iko1U1ZkejhNWVo3b0twb0pwdS9QMVE9PSIsInZhbHVlIjoiVUxyTFVmMm9XSG95VHd6cGxCVThqSExvSzJQWmQ2WWRMRGpoT0xsVjExdHl1M0xnZ2xGZjd2WDRVdHRqa1J4TU4rRjByakFoSUNHT2lPTGVUb0Z4aHNhWjRleTM0TnBjakRPRzc4WkZVWDMvTzdqNlpoVTBCRWRsOTlwcHIvNFQiLCJtYWMiOiI0MTRhMjRkNGY3Njg0ZDI4NjU1MzFmZjI2M2FkOTA5NDc4ZWJhYzhiZTA5MTFkZTQ2ZmJlY2UxNzBlZjc3MTc3IiwidGFnIjoiIn0%3D; path=/; httponly; samesite=lax, cache-control: no-cache, private, date: Mon, 01 Aug 2022 06:56:00 GMT, vary: Accept-Encoding, content-encoding: gzip, cf-cache-status: DYNAMIC, report-to: {"endpoint .......
Yes, both are same.
This is how I am saving header.
login(String phn, String password) async {
final prefs = await SharedPreferences.getInstance();
await getLocation();
String uri = "$baseUrl/User_Login";
try {
http.Response response = await http.post(Uri.parse(uri), headers: {
'Accept': 'application/json'
}, body: {
"number": phn,
"password": password,
"long": long,
"lati": lati
});
print(response.headers);
prefs.setString('header', response.headers.toString());
return json.decode(response.body);
} catch (e) {
return e;
}
}
This is how I am retrieving it and passing it to another response.
getData() async {
final prefs = await SharedPreferences.getInstance();
String? head = prefs.getString('header');
print("headers");
print(head);
Map<String, String> authHeaders = jsonDecode($head!);
// print("authHeaders");
// print(authHeaders.toString());
String uri = "$baseUrlUser/user_bal";
try {
http.Response response =
await http.get(Uri.parse(uri), headers: authHeaders);
return json.decode(response.body);
} catch (e) {
return e;
}
}
The common issue in Flutter when parsing Json data is about the type of request and it's encoding.
Even if you may post the complete source code, at least, the relevant one to your problem, like how you're performing the request, your error probably comes on how you ask for data to the remote.
If you're trying to parse the response as Json, you must specifically add the application/json;charset=UTF-8 in your headers.
But, if you read this line in your source code:
prefs.setString('header', response.headers.toString());
you're saving the headers as string in the header key. This means, that the headers are usually represented in most standars as Map datastructures, so you're asking for retrive as a String in decode(...) a probably bad formatted data.
The solution it's pretty straightfoward. Save the header(s) that your interested one by one, and then retrieve them by key, and the format should be ok to use the jsonDecode.
Edit:
getting directly your code to exemplify as requested by the OP how to get them individually. We will take the Accept header as example, as it's also the unique provide in the example code.
login(String phn, String password) async {
final prefs = await SharedPreferences.getInstance();
await getLocation();
String uri = "$baseUrl/User_Login";
try {
http.Response response = await http.post(Uri.parse(uri), headers: {
'Accept': 'application/json'
}, body: {
"number": phn,
"password": password,
"long": long,
"lati": lati
});
prefs.setString('header', response.headers.get('Accept'));
return json.decode(response.body);
} catch (e) {
return e;
}
}
Then, you only must retrieve it by key:
getData() async {
final prefs = await SharedPreferences.getInstance();
String? head = prefs.getString('Accept');
Map<String, String> authHeaders = new Map();
authHeaders['Accept'] = head!;
String uri = "$baseUrlUser/user_bal";
try {
http.Response response =
await http.get(Uri.parse(uri), headers: authHeaders);
return json.decode(response.body);
} catch (e) {
return e;
}
}
The unique difference is that you're not storing a completly Map as a String as you do in the example, you're saving the keys that you desire as what they are, Strings. Parsing JSON it's alwaya a quite sensible action, so the more granularity over the pieces you take, the best results.
Related
I am getting blank httpException message while trying to submit client certificate by using Dio package.
DioErrorType (DioErrorType.DEFAULT) : HttpException (HttpException: , uri = [API_PATH])
Same certificate is working when requesting with postman.
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Thu, 21 Jan 2021 05:56:55 GMT
Below is the code I am using
Future<List<int>> loadCertificate(String assetPath) async {
return (await rootBundle.load(assetPath)).buffer.asUint8List();
}
final List<int> certificateChainBytes =
await loadCertificate('assets/certs/client-cert1.pfx');
final List<int> keyBytes =
await loadCertificate('assets/certs/client-cert1.pfx');
final Dio dio = Dio();
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
final SecurityContext sc = SecurityContext()
..useCertificateChainBytes(certificateChainBytes, password: 'Secret')
..usePrivateKeyBytes(keyBytes, password: 'Secret');
final HttpClient httpClient = HttpClient(context: sc);
httpClient.badCertificateCallback =
(X509Certificate cert, String host, int port) {
print('badcertificatecallback');
print(cert.issuer);
return true;
};
return httpClient;
};
try {
url = url.contains('http') ? url : '${PsConfig.ps_app_url}$url';
print('API Response from $url');
final Response response =
await dio.get(url, options: Options(headers: getHeaders()));
return processHttpResponse(obj, response);
} on diolib.DioError catch (e) {
inspect(e);
return processDioResponse(obj, e);
} finally {
dio.close();
}
I am new to this and got stuck. Thank you in advance.
I am using an API that converts HTTP to JSON and to get a response from the server I need to send a post request of HTML however i'm not sure how to do that?
This is my current implementation -
Future<String> test() async {
var link =
await http.get('https://example.com');
var body = parse(link.body);
return body.outerHtml;
}
Future<Album> createAlbum(String html) async {
final http.Response response = await http.post(
'https://www.html2json.com/api/v1',
headers: <String, String>{
'Content-Type': 'text/html; charset=UTF-8',
},
body: html,
);
if (response.statusCode == 200) {
return Album.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to create album.');
}
}
I call this is when my app starts like so,
#ovveride
void initState() {
test().then((body) => createAlbum(body)); //Output returns HTTP error 301, am I doing something wrong?
super.initState();
}
Checked the following code which worked for me.
Future<Album> createAlbum(String html) async {
final http.Response response = await http.post(
'https://www.html2json.com/api/v1',
headers: <String, String>{
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body: html,
);
You need to change the Content-type to application/x-www-form-urlencoded; charset=UTF-8. This should do the trick.
Thanks to DARSH SHAH, I solved this using dio (https://pub.dev/packages/dio).
dynamic response;
Dio dio = Dio();
Future<dynamic> test() async {
dynamic link = await dio.get(
'https://example.com');
return link;
}
Future<dynamic> post(dynamic body) async {
String _baseUrl = "https://html2json.com/api/v1";
var options = Options(
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
followRedirects: false,
);
final response = await dio.post(
_baseUrl,
data: body,
options: options,
);
return response;
}
FloatingActionButton(
onPressed: () async {
dynamic responseHTML = await test();
response = await post(responseHTML.data); //This will contain the JSON response
},
);
I am trying to send a POST request to an API to create an account.
The request is working well, it should look like this :
Bulk Edit Mode :
Key-Value Edit mode :
There are also 9 headers that are auto-generated, so I did not show them, but I can take another screen if you need to.
My request looks like this :
import 'dart:convert' as convert ;
import 'package:my_project/requests/utils.dart';
import 'package:http/http.dart' as http;
Future<String> createUser(String firstName, String name, String mail,
String password, String confirmPassword, String birthDate,
String phone) async {
String url = BASE_URL + "createUser" ; // Don't worry about BASE_URL, the final url is correct
Map<String, dynamic> formMap = {
"name": name,
"surname": firstName,
"mail": mail,
"password": password,
"birth": birthDate,
"phone": phone,
"confirmPassword": confirmPassword
} ;
http.Response response = await http.post(
url,
body: convert.jsonEncode(formMap),
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
encoding: convert.Encoding.getByName("utf-8"),
);
print("RESPONSE ${response.statusCode} ; BODY = ${response.body}");
return (response.body) ;
}
Here is my print result :
I/flutter ( 6942): RESPONSE 307 ; BODY =
As you can see, I am getting a 307 error, and the problem does not come from the server, as it worked with Postman.
Am I sending this form-urlencoded POST request correctly ?
I also tried :
http.Response response = await http.post(
url,
body: "name=$name&surname=$firstName&mail=$mail&password=$password&birth=$birthDate&phone=$phone&confirmPassword=$confirmPassword",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
encoding: convert.Encoding.getByName("utf-8"),
);
but with the same results. I tried too :
http.Response response = await http.post(
url,
body: formMap,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
encoding: convert.Encoding.getByName("utf-8"),
);
with same result again.
What am I doing wrong ?
EDIT :
I tried FoggyDay answer, here is my request now :
final client = HttpClient() ;
final request = await client.postUrl(Uri.parse(url));
request.headers.set(HttpHeaders.contentTypeHeader, "application/x-www_form-urlencoded");
request.followRedirects = true ;
request.write(formMap);
final response = await request.close();
print("STATUS CODE = ${response.statusCode}");
However I still have a 307 error. Did I create the right request ?
EDIT 2 :
As asked, I printed location as follow :
final client = HttpClient() ;
final request = await client.postUrl(Uri.parse(url));
request.headers.set(HttpHeaders.contentTypeHeader, "application/x-www_form-urlencoded");
request.followRedirects = true ;
request.write(formMap);
final response = await request.close();
print("STATUS CODE = ${response.statusCode}");
print("Response headers = ${response.headers}");
And I get :
I/flutter ( 7671): STATUS CODE = 307
I/flutter ( 7671): Response headers = location: /app/createUser/
I/flutter ( 7671): date: Tue, 26 May 2020 09:00:29 GMT
I/flutter ( 7671): content-length: 0
I/flutter ( 7671): server: Apache/2.4.41 (Amazon) OpenSSL/1.0.2k-fips
The thing is I am already making a call on /app/createUser... ('/app/' is in BASE_URL)
For x-www-form-urlencoded parameters, just use this:
Future<String> login(user, pass) async {
final response = await http.post(
Uri.parse('https:youraddress.com/api'),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
encoding: Encoding.getByName('utf-8'),
body: {"title": "title"},
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
}
}
official http package from flutter is buggy with urlencoded type, you can use Dio package instead.
final dio = Dio();
final res = dio.post(
'/info',
data: {'id': 5},
options: Options(contentType: Headers.formUrlEncodedContentType),
);
As you can see, I am getting a 307 error, and the problem does not come from the server, as it worked with Postman.
No, that's NOT necessarily the case. Look here:
MDN: 307 Temporary Redirect
In other words, Postman is following the redirect ... and your Flutter app isn't.
SUGGESTION: Try setting followRedirects to true:
https://api.flutter.dev/flutter/dart-io/HttpClientRequest/followRedirects.html
ADDITIONAL INFO:
The default value for request.followRedirects happens to be "true" anyway. It doesn't hurt to explicitly set it ... but it explains why the behavior didn't change.
Per this post:
The Dart HTTP client won't follow
redirects
for POSTs unless the response code is 303. It follows 302 redirects
for GET or HEAD.
Per this post
The correct way to handle redirects on POST requests is to manually
implement an appropriate strategy for your use case:
var response = await client.post(...);
if (response.statusCode == 301 || response.statusCode == 302) {
// send post request again if appropriate
}
let try with this code, it works well for me.
var headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var request = http.Request('POST', Uri.parse('https://oauth2.googleapis.com/token'));
request.bodyFields = {
'client_id': '',
'client_secret': '',
'code': '',
'grant_type': 'authorization_code',
'redirect_uri': ''
};
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
If you are using http, you should add the below lines
Android -
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="first_app"
android:usesCleartextTraffic="true" //this line
android:icon="#mipmap/ic_launcher">
iOS -
ios/Runner/info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Be warned that you will need to have an explanation for Apple's review team when enabling this, otherwise, your app will get rejected on submission.
Uninstall the app and Reinstall again if you have the app already in the emulator when you add those lines to avoid confusions.
If you send HTTP GET request, you can use query parameters as follows:
QueryParameters
http://example.com/path/to/page?name=ferret&color=purple
The contents are encoded as query parameters in the URL
application/x-www-form- urlencoded
The contents are encoded as query parameters in the body of the
request instead of the URL.
The data is sent as a long query string. The query string contains
name-value pairs separated by & character
POST example
flutter http package version - http: ^0.13.1
import 'package:http/http.dart' as httpClient;
Future<dynamic> postData() async {
//Uri.https("192.168.1.30:5000", "/api/data")
//Uri.parse("your url");
final Uri uri = Uri.http("192.168.1.30:5000", "/api/data");
final response = await httpClient.post(
uri,
body: {
"name": "yourName",
"age": "yourAge"
},
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
encoding: Encoding.getByName('utf-8'),
);
return response.body;
}
I'm having a bit of difficulty with registering to aqueduct backend from my Flutter frontend
Here is my code in my frontend:
Future<void> signUp(String email, String password) async {
final body = "username:$email,password:$password"; //<- return request entity could not be decoded
//final body = {"username": email, "password": password}; //<- return bad state: Cannot set the body fields of Request with content-type "application/json"
try {
final http.Response response = await http.post(
"http://localhost:8888/register",
headers: {"Content-Type": "application/json"},
body: body);
final jsonResponse = json.decode(response.body);
if (jsonResponse["error"] != null) {
throw HttpException(jsonResponse["error"]);
}
} catch (error) {
throw error;
}
}
There must be some silly mistake. I believe it is with formatting body so I tried 2 options and both throw different http exception (as in comment).
Here is an example of connecting to an Aqueduct server from a Flutter client. (This isn't really a server question, though, since the client and server are independent of each other.)
Here is an example of registering:
void _register(String email, String password) async {
Map<String, String> headers = {"Content-type": "application/json"};
final jsonString = '{"username":"$email", "password":"$password"}';
Response response = await post(YOUR_URL_HERE, headers: headers, body: jsonString);
print('${response.statusCode} ${response.body}');
}
In your example you aren't encoding the JSON correctly.
And here is another example of signing in. The class is a view model architecture that I talk about here.
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
class LoginViewModel extends ChangeNotifier {
String _token = '';
bool _isLoggedIn = false;
bool get isLoggedIn => _isLoggedIn;
String get token => _token;
Future onLoginPressed(String username, String password) async {
if (username.isEmpty || password.isEmpty) {
return;
}
_isLoggedIn = await _login(username, password);
notifyListeners();
}
Future<bool> _login(String username, String password) async {
var clientID = 'com.example.app';
var clientSecret = '';
var body = 'username=$username&password=$password&grant_type=password';
var clientCredentials = Base64Encoder().convert('$clientID:$clientSecret'.codeUnits);
Map<String, String> headers = {
'Content-type': 'application/x-www-form-urlencoded',
'authorization': 'Basic $clientCredentials'
};
var response = await http.post(YOUR_URL_HERE, headers: headers, body: body);
final responseBody = response.body;
if (response.statusCode != 200) {
return false;
}
final map = json.decode(responseBody);
_token = map['access_token'];
return true;
}
}
Based off the documentation on Google Drive API I'm trying to upload a file to the root folder of a Google Drive. I have authentication of the user through Google Sign In, and that hasn't been an issue. I keep getting a 411 Error returned from the server that says
"POST requests require a Content-length header. That’s all we know.".
I have a Content-length header but it seems to not be accepted. Here's the code I have,
Uri uri = Uri.parse('https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable');
http.MultipartRequest request = new http.MultipartRequest('POST', uri);
request.headers["Authorization"] = header['Authorization'];
request.headers['content-type'] = "application/json; charset=UTF-8";
request.headers['X-Upload-Content-Type'] ='video/mp4';
request.headers['X-Upload-Content-Length'] = lengthInBytes.toString();
request.headers['name'] = fileName;
request.headers['content-length'] = (request.contentLength).toString();
//request.files.add(await http.MultipartFile.fromPath('$fileName', file.path,));
print("request.toString: " + request.toString());
http.StreamedResponse response = await request.send();
print('ok: ' + response.statusCode.toString());
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
The only line that I know looks off to me is the fileName, as the documentation on the API site is slightly different and I'm not sure if I'm encoding it correctly. Here's the API example on the Google site,
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable HTTP/1.1
Authorization: Bearer [YOUR_AUTH_TOKEN]
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: image/jpeg
X-Upload-Content-Length: 2000000
{
"name": "myObject"
}
I can do a multipart upload for a file about 5MB in size, but I need to be able to upload larger ones and resumable is the only option. I can post the multipart code that works if needed.
I solved the issue by using the http StreamedRequest class. The code posted below works with Google Drive V3 to upload a mp4 video.
Future handleUploadData(Map headers, String filename, String path) async {
final file = new File(path);
final fileLength = file.lengthSync().toString();
String sessionUri;
Uri uri = Uri.parse('https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable');
String body = json.encode({ 'name' : filename });
final initialStreamedRequest =
new http.StreamedRequest('POST', uri)
..headers.addAll({
'Authorization': headers['Authorization'],
'Content-Length' : utf8.encode(body).length.toString(),
'Content-Type' : 'application/json; charset=UTF-8',
'X-Upload-Content-Type' : 'video/mp4',
'X-Upload-Content-Length' : fileLength
});
initialStreamedRequest.sink.add(utf8.encode(body));
initialStreamedRequest.sink.close();
http.StreamedResponse response = await initialStreamedRequest.send();
print("response: " + response.statusCode.toString());
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
if (response.statusCode == 200) {
sessionUri = response.headers['location'];
print(sessionUri);
}
Uri sessionURI = Uri.parse(sessionUri);
final fileStreamedRequest =
new http.StreamedRequest('PUT', sessionURI)
..headers.addAll({
'Content-Length' : fileLength,
'Content-Type' : 'video/mp4',
});
fileStreamedRequest.sink.add(file.readAsBytesSync());
fileStreamedRequest.sink.close();
http.StreamedResponse fileResponse = await fileStreamedRequest.send();
print("file response: " + fileResponse.statusCode.toString());
fileResponse.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
The initial StreamRequest sends a request to GDrive with meta data about the file that will be uploaded, and receives a location URI that is used in the second file StreamRequest to upload the actual file data. Currently this is done in one upload action, but it could be split up into chunks.
I had roughly the same problem except I was trying to upload a text file and I wanted a single atomic request in order to be able to use the "If-Match" header with the file etag (When I'll write "update" code, I'm doing sync and I don't want to overwrite the file if it was changed by somewhere else during my sync).
I was really struggling with the http.post function and I was getting the "411 length required" error even though I was properly setting the "Content-Length" header.
The solution from Sean Coutinho using http.StreamedRequest gave me working code I could work from to get my request working, so thank you!
I'll post my code here in case it helps other people:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:google_sign_in/google_sign_in.dart';
enum RemoteFileType {
FOLDER,
FILE,
}
class RemoteFile {
final RemoteFileType fileType;
final String fileId;
final String fileName;
RemoteFile(
this.fileType,
this.fileId,
this.fileName,
);
}
// The boundary string
const String MULTIPART_REQUESTS_BOUNDARY_STRING = 'foo_bar_baz';
Map<String, String> _authHeaders;
String _createMultiPartRequestBodyString(
final Map<String, dynamic> requestMetaData,
final String fileContentString,
) {
return '\r\n--$MULTIPART_REQUESTS_BOUNDARY_STRING\r\n' +
'Content-Type: application/json; charset=UTF-8\r\n\r\n' +
jsonEncode(requestMetaData) +
'\r\n--$MULTIPART_REQUESTS_BOUNDARY_STRING\r\nContent-Type: text/plain\r\n\r\n' +
fileContentString +
'\r\n--$MULTIPART_REQUESTS_BOUNDARY_STRING--';
}
Future<RemoteFile> createNewTextFile(
final RemoteFile parentFolder,
final String fileName,
final String fileTextContent,
) async {
final Map<String, dynamic> requestMetaData = {
'mimeType': 'application/json',
'title': fileName,
'parents': [
{'id': parentFolder.fileId}
],
};
final String multiPartRequestBodyString = _createMultiPartRequestBodyString(requestMetaData, fileTextContent);
final http.StreamedRequest fileStreamedRequest = http.StreamedRequest(
'POST',
Uri.parse('https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart'),
);
fileStreamedRequest.headers.addAll({
'Authorization': _authHeaders['Authorization'],
'Accept': 'application/json',
'Content-Type': 'multipart/related; boundary=$MULTIPART_REQUESTS_BOUNDARY_STRING',
'Content-Length': multiPartRequestBodyString.length.toString(),
//'If-Match': 'my_etag_here_when_updating_existing_file_with_put',
});
fileStreamedRequest.sink.add(utf8.encode(multiPartRequestBodyString));
fileStreamedRequest.sink.close();
final http.StreamedResponse httpPostResponse = await fileStreamedRequest.send();
// Do what you want with the response too
//...
}