uploading image using file_picker flutter to a nodejs server - json

I have an api which gives the following data as response:
{
"status": 200,
"msg": "Data Found",
"data": {
"id": 104,
"firstName": "aaa",
"lastName": "aaa",
"surname": "aaa",
"email": "email#email.care",
"phone": "090909090",
"age": "23",
"gender": "M",
"height": "163",
"bloodGroup": null,
"weight": "72",
"status": null,
"fileId": 228,
"password": "pass",
"file": {
"id": 228,
"filename": "images.jpg",
"path": "user/images1613558976577.jpg",
"alt": "shafa care"
}
},
"success": true,
"token": "some token",
"userAccess": "some data"
}
The "file" parameter in the response is used to hold the image that the user uploads. For my update method, the user needs to pass their token as header for the update api. For updating the file parameter i have tried many different ways just to update the user image. The below code is using multipart form data to update the existing file image.
Future<AuthModel> updateImage(File imageFile, AuthModel authModel) async{
final String _accessToken = '${authModel.token}';
final String url =
'${GlobalConfiguration().getString('api_base_url')}auth/user/update';
var stream = new http.ByteStream(imageFile.openRead());
var length = await imageFile.length();
var uri = Uri.parse(url);
var request = new http.MultipartRequest("POST", uri);
request.headers['Authorization'] = _accessToken;
// request.headers['Content-Type'] = 'multipart/form-data';
var multipartFile = new http.MultipartFile('file', stream, length, filename: basename(imageFile.path));
request.files.add(multipartFile);
var response = await request.send();
print("updating: " + response.statusCode.toString());
response.stream.transform(utf8.decoder).listen((event) {
currentUser = authModelFromJson(event);
print("updating img: " + event);
});
return currentUser;
}
The above function does not update my file parameter even when the data is found. I just get the same old response. filepicker is also sending the correct image path that the user chooses from the gallery. I have also tried using http.client.post method using a token as the header and 'file' parameter as the body but then data is not found as the api only accepts form-data when an image is being uploaded.
It works in postman using form-data post method.
I am new to flutter and still learning. I have been stuck here for days without any solution. How can i update the file parameter from my flutter application? Any help is appreciated.

This is sample code. I hope this may help you !
static Future<bool> uploadFileAsFormData(
String url, File file) async {
try {
var uri = Uri.parse(_buildUrl(url));
var request = http.MultipartRequest('POST', uri);
request.files.add(await http.MultipartFile.fromPath('file', file.path));
var res = await request.send();
if (res.statusCode == 200) {
return true;
} else {
return false;
}
} catch (err) {
return false;
}
}

You can use this Dio to upload the image as shown by the following code:
Dio dio = Dio();
var formData = FormData();
for (var file in filePath) {
formData.files.addAll([MapEntry("files", await MultipartFile.fromFile(file)),]);
print(formData.length);
}
var response = await dio.post(url
data: formData,
options: Options(headers: {
'Authorization': _accessToken
}));
if(response.statusCode == 200){
print(response.data.toString();
}

Related

Sending a Direct Message using Twitter API using Twitter Lib from Google App Script

I am trying to send direct message through twitter api using Twitter-Lib through App-Script. Below is the definition of sendMsg fucntion
function sendMsg(user, tweet) {
var twitterKeys = {
TWITTER_CONSUMER_KEY: "<<>>",
TWITTER_CONSUMER_SECRET: "<<>>",
TWITTER_ACCESS_TOKEN: "<<>>",
TWITTER_ACCESS_SECRET: "<<>>",
}
var props = PropertiesService.getScriptProperties();
// props.deleteAllProperties()
props.setProperties(twitterKeys);
var service = new Twitterlib.OAuth(props);
if ( service.hasAccess() ) {
var user_id = '77773855';
var dm_link = 'https://api.twitter.com/1.1/direct_messages/events/new.json'
var response = service.fetch(dm_link, {
method: "POST",
muteHttpExceptions: true,
data: {"event":
{"type": "message_create",
"message_create": {
"target": {"recipient_id": user_id},
"message_data": {"text": "Hello"}
}
}
}
});
console.log(response.getResponseCode())
}
}
But when I execute this code, the response is always empty and response.getResponseCode() returns 422. Any leads on what I am doing wrong?

How to download media files in WhatsApp API which send users?

I am currently writing a chatbot for WhatsApp.
I use the 360dialog platform, which makes it possible to work with the WhatsApp Business API.
When the client sends a message, I see the following JSON object in the logs of my application:
{
"messages": [
{
"from": "77773336633",
"id": "ABGGd3c1cGY_Ago61ytHsZknvtLv",
"image": {
"id": "ffd23134-2dae-4fed-b5f8-0ce7867b6ddd",
"mime_type": "image/jpeg",
"sha256": "bd02100d961b5a1dbaae1dd645485ebbfeda77b44e82c015f1cf29b05654ccb9"
},
"timestamp": "1605703542",
"type": "image"
}
],
"contacts": [
{
"profile": {
"name": "Nurzhan Nogerbek"
},
"wa_id": "77773336633"
}
]
}
I can't find any information in the documentation about how to download this file.
In my case, I want to upload this image file that the client sends to my file storage.
Please tell me which URL method from the WhatsApp API is responsible for this mechanism?
P.S. At the same time, I can send files to clients. This information is available on the official documentation.
May be it will help, just try, take a look:-
const URL = `https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1104480873777230&ext=1662705250&hash=ATuMx352sLrhKUegbQZSC8oLl3J5Vy3Z49lO4HwTUKWRYQ`;
const FROM = `video`;
const config = {
method: 'get',
url: URL, //PASS THE URL HERE, WHICH YOU RECEIVED WITH THE HELP OF MEDIA ID
headers: {
'Authorization': `Bearer ${token}`
},
responseType: 'arraybuffer'
};
axios(config)
.then(function (response) {
const ext = response.headers['content-type'].split("/")[1];
fs.writeFileSync(`${FROM}.${ext}`, response.data);
})
.catch(function (error) {
console.log(error);
});
It was very tricky because postman worked, but c# didn't work for me, and I spent two days trying to find the solution and finally did the following code, which works in C#:
using HttpClient _httpClient = new HttpClient();
Uri uri = new Uri(mediaUrl);
var fileName = $"{DateTime.Now.ToString("yyyyMMddhhmmss")}.jpeg";
string filePath = $"Files\\{fileName}";
// NOTE: to save bandwidth, request compressed content
_httpClient.DefaultRequestHeaders.AcceptEncoding.Clear();
_httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
_httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
_httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));
// NOTE: accept all languages
_httpClient.DefaultRequestHeaders.AcceptLanguage.Clear();
_httpClient.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("*"));
// NOTE: accept all media types
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("image/jpeg"));
var productValue = new ProductInfoHeaderValue("ScraperBot", "1.0");
var commentValue = new ProductInfoHeaderValue("(+http://www.API.com/ScraperBot.html)");
_httpClient.DefaultRequestHeaders.UserAgent.Add(productValue);
_httpClient.DefaultRequestHeaders.UserAgent.Add(commentValue);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", {WhatsApp_Access_Token});
HttpResponseMessage response = await _httpClient.GetAsync(uri);
response.EnsureSuccessStatusCode();
var mediaType = response?.Content?.Headers?.ContentType?.MediaType ?? string.Empty;
var imageBytes = await response.Content.ReadAsByteArrayAsync();
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
fs.Write(imageBytes, 0, imageBytes.Length);
}
Here, {WhatsApp_Access_Token} is your Whatsapp API permanent token.
Ping me in a comment, please, if you have any issues or questions.
The official documentation has a session for this in https://developers.facebook.com/docs/whatsapp/api/media.
Basically you must make a GET request to download the media.
curl --request GET \
--url https://waba.360dialog.io/v1/media/{media id} \
--header 'D360-API-KEY: {your api token}'

how to post json array on flutter

I have some problem to post json array with flutter.
When I hit api with postman using json it works. Screenshot postman:
Since I know on body just accept Map <String,String> CMIIW
so i turn body into like this
List<Map<String,String>> products = [
{
"product_id": "1",
"buy_quantity": "1",
"product_price": "1000",
"is_voucher": "0",
},
{
"product_id": "2",
"buy_quantity": "2",
"product_price": "2000",
"is_voucher": "0",
},
];
final String jsonProduct = json.encode(products);// here im trying to
Map<String,String> _body = {
"buyer_id": '',
"buyer_firstname": postCart.buyerFirstname,
"phone_number": postCart.phoneNumber,
"transaction_total_price": postCart.transactionTotalPrice.toString(),
"voucher_id": 0.toString(),
"voucher_code": 0.toString(),
"payment_id": postCart.paymentId.toString(),
"payment_name": postCart.paymentName,
"products" : jsonProduct
};
but i still got error,
thanks!
I'm assuming that you are using the http package.
This is an example of how to make an HTTP POST request with a json payload on the body:
Future<Lead> createLead(String clientName, String clientEmail, String clientPhone, String eventId) async {
// Create storage
final storage = new FlutterSecureStorage();
// Get API url from env
String url = (DotEnv().env['BASE_URL'] + "/leads/create");
String authToken = await storage.read(key: 'api-token');
// Create some request headers
Map<String, String> requestHeaders = {
'Content-type': 'application/json',
'Accept': 'application/json',
'X-Token': authToken
};
final response = await http.post(
url,
// enconde some JSON data on the request body
body: json.encode(
{
'event_id': eventId,
'name': clientName,
'phone': clientPhone,
'email': clientEmail
}
),
headers: requestHeaders
);
if (response.statusCode == 200) {
final leadsJson = json.decode(response.body);
Lead lead = Lead.fromJson(leadsJson);
return lead;
} else {
// If that response was not OK, throw an error.
// throw Exception('Failed to load post');
return null;
}
}
Hope it helps.
If you want to achieve the JSON in the screen shot you need to make several changes.
Notice that the list of products shows unquoted integers when converted to JSON, so these need to be kept as ints in your Dart class. (Note the preferred syntax, too.)
var products = <Map<String, int>>[
{
'product_id': 1,
'buy_quantity': 1,
'product_price': 1000,
'is_voucher': 0,
},
{
'product_id': 2,
'buy_quantity': 2,
'product_price': 2000,
'is_voucher': 0,
},
];
The type of _body needs to change because it now contains a list as well as strings. (Keep the rest the same - like the toStrings - as your screenshot shows that even the integers are quoted as strings.)
var _body = <String, dynamic>{
'buyer_id': '',
'buyer_firstname': postCart.buyerFirstname,
'phone_number': postCart.phoneNumber,
'transaction_total_price': postCart.transactionTotalPrice.toString(),
'voucher_id': 0.toString(),
'voucher_code': 0.toString(),
'payment_id': postCart.paymentId.toString(),
'payment_name': postCart.paymentName,
'products': products
};
Lastly json and (preferably) utf8 encode the resulting map, and pass that as the body parameter of your http.post.
var bytes = utf8.encode(json.encode(_body));
await http.post(url, body: bytes, headers: someHeaders);
One of your headers could be content-type: application/json;encoding=utf-8 to tell the server that you are sending UTF8 encoded JSON.

Autodesk Forge: Translation Failed - File to bucket data: fileContent

I've been following this viewer walkthrough tutorial (node.js), for uploading and showing a file in the forge viewer.
I've been using angular to recreate the example, except instead of a user uploading a file, the file is hardcoded into the app from my assets folder for testing purposes.
The issue comes to when i try and translate the revit file into svf.
I know there isn't an issue with the revit file as i have used models.autodesk.io to check if all is good.
I can successfully create a bucket and post a job, but when calling the translation status to check if translation is completed, i receive this:
{
"type": "manifest",
"hasThumbnail": "false",
"status": "failed",
"progress": "complete",
"region": "US",
"urn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6OTA0ZmZmYmMtODI1Ni00OWY2LWI3YzYtNDI3MmM1ZDlmNDljL2RyYXBlLnJ2dA",
"version": "1.0",
"derivatives": [
{
"name": "drape.rvt",
"hasThumbnail": "false",
"status": "failed",
"progress": "complete",
"messages": [
{
"type": "error",
"code": "Revit-UnsupportedFileType",
"message": "<message>The file is not a Revit file or is not a supported version.</message>"
},
{
"type": "error",
"message": "Possibly recoverable warning exit code from extractor: -536870935",
"code": "TranslationWorker-RecoverableInternalFailure"
}
],
"outputType": "svf"
}
]
}
I'm pretty sure my code for translating a project is correct, i think the issue is coming from uploading the file to my bucket.
The body structure for the PUT request must contain the contents of the file.
Here is my code for loading and reading a file using XMLHttpRequest and FileReader
loadFile(bucketKey, accessToken) {
const reader: XMLHttpRequest = new XMLHttpRequest();
reader.open('GET', './assets/drape.rvt', true);
reader.responseType = 'blob';
reader.onloadend = (request) => {
const blob: Blob = reader.response;
console.log(blob); //returns Blob {size: 372736, type: "text/xml"}
// Create file from blob
const modelFile: File = new File([blob], 'drape.rvt');
this.readFile(bucketKey, accessToken, modelFile);
};
reader.send();
}
readFile(bucketKey, accessToken, modelFile) {
const myReader: FileReader = new FileReader();
myReader.readAsArrayBuffer(modelFile);
myReader.onloadend = (e) => {
const arrayBuffer: ArrayBuffer = myReader.result as ArrayBuffer;
this.fileToBucket(bucketKey, accessToken, arrayBuffer);
};
}
And the put request:
fileToBucket(bucketKey, accessToken, fileContent) {
const encodedBucketKey = encodeURIComponent(bucketKey);
const encodedFileName = encodeURIComponent('drape.rvt');
const uploadURI = `https://developer.api.autodesk.com/oss/v2/buckets/${encodedBucketKey}/objects/${encodedFileName}`;
const options = {
headers: new HttpHeaders({
'Content-Type': 'application/octet-stream',
Authorization: 'Bearer ' + accessToken
})
};
const body = {
data: fileContent
};
this.http.put(uploadURI, body, options)
.subscribe(
success => {
// URL safe base64 encoding
const urn = btoa(success.objectId);
this.translateObject(accessToken, urn);
}, error => {
console.log('fileToBucket');
console.log(error);
});
}
I'm assuming that the file content is the issue, here is the equivalent using node.js for the tutorial: PUT request read file.
You can use a utility web app like https://oss-manager.autodesk.io/ to check if the file you previously uploaded is correct (by downloading it or trying to translate it to SVF through the app's UI) and upload the file using this utility and then try to translate it with your app. It can also be used to delete all the derivatives for a given file in your bucket.
That could help narrow down the issue.
It's also possible that the file was not correctly uploaded the first time (at a certain point when you were still testing things) and so the translation failed back then and now it won't try to translate the file again. You can force the translation to take place by adding x-ads-force to the POST Job request with value "true" - see https://forge.autodesk.com/en/docs/model-derivative/v2/reference/http/job-POST/

Web API: Reading JSON file using StreamContent converting Caffè to Caff (è is missing)

I am reading a big JSON file stored on the server, using WEB API. Following is the code snippet:
public HttpResponseMessage Get()
{
string filePath = "file path";
var response = Request.CreateResponse(HttpStatusCode.OK);
if (File.Exists(filePath))
{
response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
}
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return response;
}
Everything is working as expected. Apart from a string "Caffè", which is converted to "Caff". (è to space).
Does anyone know what's going on under the hood and the fix?
Sample of JSON file:
{
"id": 1,
"PartnerName":"Caffè Nero"
},
{
"id": 2,
"PartnerName":"XYZ"
},
JSON response of Get() method is returning right JSON except, Caffè Nero
Response:
{
"id": 1,
"PartnerName":"Caff Nero"
},
{
"id": 2,
"PartnerName":"XYZ"
},