Flutter: upload image using binary body - dart

I want to upload a file using binary body like in the screenshot:
So far I just have:
save() async {
http.put(url,headers:headers, body: );

The body parameter of the put method accepts a List<int> that will be used as a list of bytes
From the http API reference: https://pub.dev/documentation/http/latest/http/put.html
body sets the body of the request. It can be a String, a List or
a Map. If it's a String, it's encoded using encoding
and used as the body of the request. The content-type of the request
will default to "text/plain".
If body is a List, it's used as a list of bytes for the body of the
request.
If body is a Map, it's encoded as form fields using encoding. The
content-type of the request will be set to
"application/x-www-form-urlencoded"; this cannot be overridden.
Examples to send a file:
main() async {
await put(url, body: File('the_file').readAsBytesSync());
}

You can use this for upload Image
Future uploadImage(File imageFile)async{
var stream= new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
var length= await imageFile.length();
var uri = Uri.parse("Image upload url");
var request = new http.MultipartRequest("POST", uri);
var filename = "Your image name";
var multipartFile = new http.MultipartFile("image", stream, length, filename: basename(filename));
request.files.add(multipartFile);
var response = await request.send();
if(response.statusCode==200){
print("Image Uploaded");
}else{
print("Upload Failed");
}
}

Related

Trying to upload media to the Meta Whatsapp API but running into errors

Context: I need to send media templates in which I need to send local files. Thus I need to upload the files to the WhatsApp API to get the Media Id, which I can then use to send the message templates.
The issue: I am running into errors while sending the post request to the server through DART. However the same call is working when sent through postman. I have tried sending the data both as a JSON and as form-data, but both are returning errors. I am attaching the code below, as well as the errors I am facing. Any help is really appreciated.
Getting the file path
upload() async{
if(await Permission.storage.isGranted){
FilePickerResult? choice = await FilePicker.platform.pickFiles(allowMultiple: false);
String? path = choice?.files.single.path;
if(path != null){
uploadJson(path);
// uploadFormData(path);
}
}else{
Permission.storage.request();
}
}
Uploading JSON
uploadJson(String path) async{
File imgfile = File(path);
Uint8List imgbytes = await imgfile.readAsBytes();
String bs4str = base64.encode(imgbytes);
print(bs4str);
var headers = {
'Authorization': variables.authorizationToken,
"Content-Type": 'application/json',
};
var body = jsonEncode({
'file': '$bs4str;type=image/jpeg',
'messaging_product':'whatsapp'
});
Response response = await post(Uri.parse('${variables.baseURL}${variables.phoneNumberId}/media'), headers: headers, body: body);
print(response.body);
}
Uploading as Form-data
uploadFormData(String path) async {
var headers = {
'Authorization': 'Bearer EAAGtvNhUHUIBANf5KvyxnZCUKcRn3jTJgPZBR2AbbVhZBZBO7GjoDCnS26FQT6Nr6qdRV993ZCJEbGwiqZCdQ7TZBJX8S6KXQdOTgmSf9ue7GCEN1IL3yqfAUEIN1bw0nyvptHeZBFCsdfwpxZAcS1ZCbCdmqArZC81orVbYRkzJy1h7ChOAygmrchfFtJAapykZAadruFqOWwcVvtudMezse94zENBNVZA0k7pAZD',
};
var request = MultipartRequest('POST', Uri.parse('https://graph.facebook.com/v14.0/106822672107550/media'));
request.fields.addAll({
'messaging_product': 'whatsapp'
});
request.files.add(await MultipartFile.fromPath('file', path));
request.headers.addAll(headers);
Response response = await Response.fromStream(await request.send());
print(response.body);
}
Error for JSON:
flutter: {"error":{"message":"An unknown error has occurred.","type":"OAuthException","code":1,"fbtrace_id":"AE72st2KT8wJFQ_wYvrcJY6"}}
Error for Form-Data:
flutter: {"error":{"message":"(#100) Param file must be a file with one of the following types: audio\/aac, audio\/mp4, audio\/mpeg, audio\/amr, audio\/ogg, audio\/opus, application\/vnd.ms-powerpoint, application\/msword, application\/vnd.openxmlformats-officedocument.wordprocessingml.document, application\/vnd.openxmlformats-officedocument.presentationml.presentation, application\/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application\/pdf, text\/plain, application\/vnd.ms-excel, image\/jpeg, image\/png, image\/webp, video\/mp4, video\/3gpp. Received file of type 'application\/octet-stream'.","type":"OAuthException","code":100,"fbtrace_id":"AfsxKl38CW7hUF_ixMzNha9"}}
The problem was with the Mime-type of the file. The Multi-Part file class needed the mime-type of the file to be declared while uploading the file, or the file was automatically being uploaded as an octlet-stream. The code to the working request is posted below.
var request = http.MultipartRequest('POST', Uri.parse('https://graph.facebook.com/v14.0/${variables.phoneNumberId}/media'));
request.headers.addAll({
'Authorization': variables.authorizationToken,
'Content-Type': 'multipart/form-data'
});
request.fields.addAll({
'messaging_product': 'whatsapp',
'type': 'application/pdf'
});
// The MIME type of the image or file
const mimeType = 'application/pdf';
// Open the image file
var file = File(path);
// Create a MultipartFile from the File object
final multipartFile = await http.MultipartFile.fromPath(
'file',
file.path,
contentType: MediaType.parse(mimeType),
);
// Create a request body containing the multipart file
request.files.add(multipartFile);
// Send the request
final response = await request.send();
// Check the response status code
if (response.statusCode == 200) {
String body = await response.stream.bytesToString();
var json = jsonDecode(body);
print(json['id']);
} else {
print(response.reasonPhrase);
}

Flutter: How do I upload a JSON file to a URL?

I've been searching in vain for a simple way of uploading a JSON file to a specific URL but I haven't been able to find one, for Flutter.
I have implemented the code to download a simple JSON file from a specific URL. What I haven't been able to find is how to upload the same file to same location.
Do I need to do the multipart stuff? And I'm not even sure how that works.
EDIT
I'm starting with Map data (Map) and I want to upload it to a server as JSON (text file). This code is specific to binary data. And yes, I'm just writing to a URL, not an endpoint:
Upload(File imageFile) async {
var stream = new
http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
var length = await imageFile.length();
var uri = Uri.parse(uploadURL);
var request = new http.MultipartRequest("POST", uri);
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
//contentType: new MediaType('image', 'png'));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
To upload files to an endpoint, you can use http.MultipartRequest - this allows you to upload files with binary content (images, docs, etc.) and files with regular text.
import 'package:http/http.dart' as http;
String url = // your endpoint
var req = http.MultipartRequest('POST', Uri.parse(url));
Then to upload
var request = http.MultipartRequest('POST', Uri.parse(url));
request.files.add(
await http.MultipartFile.fromPath(
'json',
filePath
)
);
var res = await request.send();

Image upload to server using dart, flutter

upload(File imageFile) async {
var uploadURL = "http://xxxxxx.org.xx/appdata/members/images";
var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
var length = await imageFile.length();
var uri = Uri.parse(uploadURL);
var request = new http.MultipartRequest("POST", uri);
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});}
But, it is throwing statuscode 301 and no file is uploaded to server's destination folder. what could be wrong?
The 301 HTTP code means that the server is trying to redirect you to another URL - see wikipedia's list of response codes.
I'd guess that your request has been redirected and the client isn't following... although MultipartRequest's followRedirects should be true by default you could try setting that explicitly, and you could increase maxRedirects.
I'd suggest testing out the API you're trying to use with curl (or similar) to make sure it's working as expected before trying with flutter.

Processing an Image in Dart

I am currently trying to process an image on the server that was uploaded by a user. My goal is to take this image that was uploaded, process it on the server and then upload it to rackspace cloud files. I have had no luck in finding a way. I am hoping that someone can lead me into the correct direction.
Heres what I have so far on the server side for processing
Future < Null > handleUploadRequest(final HttpRequest httpRequest) async {
print('handle upload -------------------------');
var data;
await httpRequest.fold(new BytesBuilder(), (b, d) => b..add(d)).then((builder) {
data = builder.takeBytes();
String encodedData = JSON.encode(data);
int dataLength = encodedData.length;
// Uploading image to rackspace cloud files
// Here we have to send a request with username & api key to get an auth token
http.post(tokens, headers : {'Content-Type':'application/json'}, body: JSON.encode({"auth": {"RAX-KSKEY:apiKeyCredentials":{"username":"XXXXXXXXXXXXXXX","apiKey":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"}}})).then((response) {
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
return response;
}).then((response){
authResponse = JSON.decode(response.body);
String token = authResponse['access']['token']['id'];
/////////// This is where we upload the image to Rackspace ///////
var request = new http.MultipartRequest("PUT", Uri.parse('https://storage101.iad3.clouddrive.com/v1/MossoCloudFS_XXXXXXX/TestContainer/testimage.jpg'));
request.headers['X-Auth-Token'] = token;
request.headers['Content-Type'] = 'image/jpeg';
var stream = new http.ByteStream.fromBytes(data);
request.files.add(new http.MultipartFile('file', stream, data.length, filename: 'testfile.jpg', contentType: 'image/jpeg');
print('requesT: ${request}');
request.send().then((response) {
print(response.statusCode);
print(response.headers);
print(response.stream);
if (response.statusCode == 200) print("Uploaded!");
});
//// End of Upload to Rackspace //////////
print('Upload Complete!');
httpRequest.response.write(data);
await httpRequest.response.close();
}
The only issue right now is that in https://pub.dartlang.org/packages/http, I need to call the type MediaType in the parameter content-type. I have no idea how to call this. It seems like it is a factory inside a class? If I do not call a content-type then it defaults to octet-stream which cannot be opened from the cdn storage container.
Reference to this way of uploading is from How can I upload a PDF using Dart's HttpClient?
Looks like an missing return before http.put(...) and httpRequest.response.close();
Either you use await before each async call (call to functions which return a Future) or return each such Future to the caller to preserve order of execution. Without any of these the async execution is scheduled for later execution and the next line of your code is executed instead before the async code you called even started.
Update pure async/await implementation
import 'package:http/http.dart' as http;
import 'dart:async' show Future, Stream;
import 'dart:io';
Future<Null> handleUploadRequest(final HttpRequest httpRequest) async {
print('handle upload -------------------------');
print('httpRequest: ${httpRequest.headers}');
var data;
var builder = await httpRequest.fold(new BytesBuilder(), (b, d) => b..add(d));
data = builder.takeBytes();
print('bytes builder: ${data}');
// Uploading image to rackspace cloud files
var url =
'https://storage101.dfw1.clouddrive.com/v1/{accountnumber}/{container}/';
var response = await http.put(url,
headers: {
'X-Auth-Token': '{XXXXXXXXXAPI_KEYXXXXXXXXXX}',
'Content-Type': 'image/jpeg',
'Content-Length': '${httpRequest.headers.contentLength}',
},
body: data);
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
print('closing connection with data complete');
httpRequest.response.write(data);
await httpRequest.response.close();
}

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