Downloading a file using Dart GDrive api with authorized GET request - dart

I'm coding in Dart and need to download a file (i.e. an image file) from google GDrive using OAuth2.0. I am at the point in my code where I have the downloadURL after having used the Dart drive_v2_api_browser client library.
I tried directly passing this to the "src" attribute
_image = new ImageElement(src: file.downloadUrl, width: file.imageMediaMetadata.width, height: file.imageMediaMetadata.height);
_image.onLoad.listen(onData, onError: onError, onDone: onDone, cancelOnError: true);
but that yielded a 403 forbidden error. That's when I realized I need to make an "authorized GET request". So I tried following the example listed on the Dart Auth pub package https://pub.dartlang.org/packages/google_oauth2_client, but I don't understand what it asking for.
This is what I am trying:
var auth = new oauth.SimpleOAuth2(_picker.Token.data);
var request = new HttpRequest();
request.onLoad.listen(onData_Request, onError: onError_Request, onDone: onDone_Request, cancelOnError: true);
request.open("request", file.downloadUrl);
auth.authenticate(request).then((request) => request.send());
but it keeps giving me an error:
token.... Method request is not allowed by Access-Control-Allow-Methods.
Does anyone have a working example of downloading a file through the Dart GDrive api relative to OAuth2.0?
Update: After Günter Zöchbauer help I was able to continue and convert the blob as such:
Adding this line to the request object:
_downloadRequest.responseType = "blob";
Allowed me to use a file reader:
void onData_Request(Event e) {
Blob response = _downloadRequest.response;
final FileReader reader = new FileReader();
reader.onLoad.listen((e) {
_handleData(reader);
});
reader.readAsArrayBuffer(response);
}
void _handleData(FileReader reader) {
Uint8List uintlist = new Uint8List.fromList(reader.result);
String charcodes = new String.fromCharCodes(uintlist);
_loadImage(_image, charcodes, 225, 225);
}
void _loadImage(ImageElement imageE, String data, int iWidth, int iHeight) {
_imageAsbase64 = window.btoa(data);
_image = new ImageElement(src: "data:image/png;base64," + _imageAsbase64, width: iWidth, height: iHeight);
_image.onLoad.listen(onData, onError: onError, onDone: onDone, cancelOnError: true);
}
void onData(Event e) {
print("success: ");
_context.drawImage(_image, 0, 0);
}

As the error message says request is not a valid HTTP method.
You need something like GET, PUT, POST, DELETE, ...
see also http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Related

Flutter camera image to api

I am at the Point where i call the Flutter Camera package, take a photo and save it temporary in my app using pathProvider. Now i want so upload this image to an api using the Dio package. My pathprovider is able to give me a String with the Path to the image. With this path i am able to display the Image using the Image widget from Flutter. however i am not able to send it to an api.
processImage(file) async {
print(file);
// /var/mobile/Containers/Data/Application/7915E945-4582-4586-8062-F73537283283/Library/Caches/2019-07-22 13:35:36.243335.png
var newfile = File(file);
Dio dio = new Dio();
FormData formData =
new FormData.from({"size": "auto", "image_file": newfile});
try {
final response = await dio.post(
"YYYYYYYYYYYY",
data: formData,
options: Options(
headers: {'X-Api-Key': 'XXXXXXX'},
),
onSendProgress: (int sent, int total) {
print("send $sent / $total");
},
onReceiveProgress: (int sent, int total) {
print("receive $sent / $total");
},
);
} on DioError catch (e) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx and is also not 304.
print(e);
}
// print(response);
}
The Dio library that has a class called UploadFileInfo which you can use for your case:
FormData formData =
new FormData.from({
"size": "auto",
"image_file": UploadFileInfo(newfile, "file_name.txt")},
);

How to mock HttpClientResponse to return a String

I am trying to write a test after refactoring to dart:io.HttpClient following https://flutter.io/networking/
Everything seems to work well up until
var responseBody = await response.transform(utf8.decoder).join();
The following test throws a NoSuchMethodError: The method 'join' was called on null.
MockHttpClient http = new MockHttpClient();
MockHttpClientRequest request = new MockHttpClientRequest();
MockHttpHeaders headers = new MockHttpHeaders();
MockHttpClientResponse response = new MockHttpClientResponse();
MockStream stream = new MockStream();
when(http.getUrl(Uri.parse('http://www.example.com/')))
.thenReturn(new Future.value(request));
when(request.headers)
.thenReturn(headers);
when(request.close())
.thenReturn(new Future.value(response));
when(response.transform(utf8.decoder))
.thenReturn(stream);
when(stream.join())
.thenReturn(new Future.value('{"error": {"message": "Some error"}}'));
I did see How to mock server response - client on server side, but that uses the http package, not dart:io.
I also tried https://github.com/flutter/flutter/blob/master/dev/manual_tests/test/mock_image_http.dart but that also returns a null.
Much thanks in advance!
The problem is that when you mock stream you actually need to implement a ton of different methods to get it to work properly. It is better to use a real Stream if you can like in the example in the flutter repo. To make sure your body is correctly set, use the utf8 encoder.
final MockHttpClientResponse response = new MockHttpClientResponse();
// encode the response body as bytes.
final List<int> body = utf8.encode('{"foo":2}');
when(response.listen(typed(any))).thenAnswer((Invocation invocation) {
final void Function(List<int>) onData = invocation.positionalArguments[0];
final void Function() onDone = invocation.namedArguments[#onDone];
final void Function(Object, [StackTrace]) onError = invocation.namedArguments[#onError];
final bool cancelOnError = invocation.namedArguments[#cancelOnError];
return new Stream<List<int>>.fromIterable(<List<int>>[body]).listen(onData, onDone: onDone, onError: onError, cancelOnError: cancelOnError);
});

Dart: Processing an uploaded file on the server from client request

I am trying to process images uploaded from client on the server but am receiving the following errors. Am I processing the httpRequest wrong?
Unhandled exception:
Uncaught Error: HttpException: Connection closed while receiving data, uri = /api/upload
/// Client Code (dart file) (Works # sending request)
sendData(dynamic data) {
final req = new HttpRequest();
FormData fd = new FormData();
fd.append('uploadContent', data);
fd.appendBlob('uploadContent', data);
req.open("POST", "http://127.0.0.1:8080/api/upload", async: true);
req.send(fd);
req.onReadyStateChange.listen((Event e) {
if (req.readyState == HttpRequest.DONE &&
(req.status == 200 || req.status == 0)) {
window.alert("upload complete");
}
});
}
InputElement uploadInput = document.querySelector('#sideBar-profile-picture');
uploadInput.onChange.listen((Event event){
// read file content as dataURL
final files = uploadInput.files;
if (files.length == 1) {
File file = files[0];
FileReader reader = new FileReader();
reader.onLoad.listen((e) {
print('results: ${reader.result}');
sendData(reader.result);
});
reader.readAsArrayBuffer(file);
}
});
I have a small server listening for the request (/api/upload) and calling handleUploadRequest with the httpRequest being passed in as the param.
Server code (This is where I am stuck)
Future<Null> handleUploadRequest(final HttpRequest httpRequest) async {
httpRequest.fold(new BytesBuilder(), (b, d) => b..add(d)).then((builder) {
var data = builder.takeBytes();
print('bytes builder: ${data}');
});
}
I am trying to read the data so that I can store it on a cdn but never get a chance to since the connection always gets closed while receiving the data.
Any help on being able to complete this is appreciated. Been at this for the past couple days:/
It is hard to tell when/if you close the httpRequest. If you are doing it right after handleUploadRequest returns, it will indeed close the connection as you are not waiting for httpRequest.fold() to complete. Adding await as shown below and making sure to call httpRequest.close() after this function complete asynchronously should work
Future<Null> handleUploadRequest(final HttpRequest httpRequest) async {
await httpRequest.fold(new BytesBuilder(), (b, d) => b..add(d)).then((builder) {
var data = builder.takeBytes();
print('bytes builder: ${data}');
});
}
(FYI) I have a similar code that works when testing with curl and uploading a file

Dart Language: receive a file from a POST and print its contents on the server

I would like to know how can a server side application receive a file (via POST) and then print its contents on the server side.
The most "up to date" related question here was this one: Dart how to upload image
But it is not working anymore (Uncaught Error: type 'String' is not a subtype of type 'HttpBodyFileUpload' of 'fileUploaded').
EDIT:
This is how I send the file (this method is working fine):
import 'dart:html';
import 'dart:async';
HttpRequest request = new HttpRequest();
final _HOST = "127.0.0.1", _PORT = 8123;
Future sendFile(File file) {
var completer = new Completer(); // No need for a Completer. It will be removed.
Uri uri = new Uri(host: _HOST, port: _PORT);
request.open("POST", uri.toString());
var filename = file.name;
final FormData formData = new FormData();
formData.append('file', filename);
request.onLoadEnd.listen((_) {
completer.complete(request.response);
});
request.send(formData);
return completer.future;
}
The server side (I'm stuck here):
void _handlePost(HttpRequest req) {
HttpBodyHandler.processRequest(req).then((body) {
HttpBodyFileUpload fileUploaded = body.body['file'];
print(fileUploaded.content);
});
}
You are appending the filename instead of the Blob (File) to your FormData object. In Dart it looks like there is a special function for appending blobs called appendBlob(name, blob, [filename]).

How can I upload a PDF using Dart's HttpClient?

I need to post a PDF file to a remote REST API, and I can't for the life of me figure it out. No matter what I do, the server responds that I have not yet associated an object with the file parameter. Let's say that I have a PDF called test.pdf. This is what I've been doing so far:
// Using an HttpClientRequest named req
req.headers.contentType = new ContentType('application', 'x-www-form-urlencoded');
StringBuffer sb = new StringBuffer();
String fileData = new File('Test.pdf').readAsStringSync();
sb.write('file=$fileData');
req.write(sb.toString());
return req.close();
Thus far, I've tried virtually every combination and encoding of the data that I write() to the request, but to no avail. I've tried sending it as codeUnits, I've tried encoding it using a UTF8.encode, I've tried encoding it using a Latin1Codec, everything. I'm stumped.
Any help would be greatly appreciated.
You can use MultipartRequest from the http package :
var uri = Uri.parse("http://pub.dartlang.org/packages/create");
var request = new http.MultipartRequest("POST", url);
request.fields['user'] = 'john#doe.com';
request.files.add(new http.MultipartFile.fromFile(
'package',
new File('build/package.tar.gz'),
contentType: new ContentType('application', 'x-tar'));
request.send().then((response) {
if (response.statusCode == 200) print("Uploaded!");
});
Try using the multipart/form-data header rather than x-www-form-urlencoded. This should be used for binary data, also can you show your full req request?
void uploadFile(File file) async {
// 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 "idDocumentOne_1" is a key of the API request
MultipartFile multipartFile = await http.MultipartFile.fromPath(
'idDocumentOne_1',
file.path
);
// add file to multipart
request.files.add(multipartFile);
// send request to upload file
await request.send().then((response) async {
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}).catchError((e) {
print(e);
});
}
I used file picker to pick file.
Here is the codes for pick file.
Future getPdfAndUpload(int position) async {
File file = await FilePicker.getFile(
type: FileType.custom,
allowedExtensions: ['pdf','docx'],
);
if(file != null) {
setState(() {
file1 = file; //file1 is a global variable which i created
});
}
}
here file_picker flutter library.

Resources