Select document file from phone and upload to server - node.js

I am trying to get a document file from phone storage when button is pressed and than upload it server. But i don't know which library to use and how to do it.

If you are willing to use a library you have both React-native-fetch-blob or axios.
If React-native-fetch-blob you can do it like this:
RNFetchBlob.fetch('POST', 'http://www.example.com/upload-form', {
Authorization : "Bearer access-token",
otherHeader : "foo",
'Content-Type' : 'multipart/form-data',
}, [
// element with property `filename` will be transformed into `file` in form data
{ name : 'avatar', filename : 'avatar.png', data: binaryDataInBase64},
// custom content type
{ name : 'avatar-png', filename : 'avatar-png.png', type:'image/png', data: binaryDataInBase64},
// part file from storage
{ name : 'avatar-foo', filename : 'avatar-foo.png', type:'image/foo', data: RNFetchBlob.wrap(path_to_a_file)},
// elements without property `filename` will be sent as plain text
{ name : 'name', data : 'user'},
{ name : 'info', data : JSON.stringify({
mail : 'example#example.com',
tel : '12345678'
})},
]).then((resp) => {
// ...
}).catch((err) => {
// ...
})
You will hae to manage to get the file path from libraries like RNFS or even RNFetch blob.
https://github.com/wkh237/react-native-fetch-blob
You can use axios too (https://github.com/mzabriskie/axios), but I don't use it so I can't help you any further.
The difference between both is the way they send the data. RNFB uses the fetch api and goes down to native to get the Base64 encoding, axios works over XMLHttpRequests, which is more likely to be used in internet browsers.
Hope it helps.

Related

Salesforce Rest API - Inserting values into Lookup fields

Inserting 200 records at a time (JSON array) into a custom object using the Salesforce REST API. Example with one record:
{
"records": [
{
"attributes" : {"type" : "Timecard__c"},
"Project__c": "a9S1F0000004LHDUA2",
"Milestone__c": "a9F1F00000007GOUAY",
"Resource__c": "0031F00000TApKqQAL",
"Date__c": "2020-08-16",
"Hours__c": 7,
"Notes__c": "Did some work"
},
]
}
The first three fields are lookups to other objects. The data I'm given to insert has names for the lookup fields (eg Project__c = "Canoe reconstruction", Milestone__c = "Rebuild gunwales", Resource__c = "John Smith".
My current plan is to generate arrays of Projects, Milestones, and Resources containing the Ids and Names then patch the JSON I have to load.
Does the Salesforce REST API offer a way to set the values of the Lookups to the text name such that it would find the Id on its own or is my current approach the most efficient way to handle this?
Here's the code I'm using for the processed data load...
const submitTimecards = async() => {
const token = await getAccessToken()
const data = JSON.parse(fs.readFileSync('timecards.json', 'utf-8'))
const response = await axios({
method: 'post',
url: `${salesforceUrl}/composite/sobjects`,
data,
headers: {
'Authorization': `OAuth ${token}`,
'Content-Type': 'application/json'
}
})
return response
}
By Name it's bit tricky. SF "natural" way would be to specify a helper field marked as external id (ideally it'd be marked unique too) and then you can use your references. "Dear Salesforce, I don't care what's your internal primary key of that Account record I need to link to, on my end it's 12345, go do your magic, look it up yourself".
It's in https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_upsert.htm?search_text=patch, look for example that says "Upserting Records and Associating with an External ID". It might not be very clear but if you have SF admin in team he/she should know what can be done with "upsert" operation in Data Loader, same principles would apply. I have an example that upserts multiple objects in one go, it'll be bit too crazy but try to read it: https://salesforce.stackexchange.com/a/274696/799
Or you could batch multiple requests into one all-or-none API call. It'll be like series of instructions to SF, not multiple round trips to you and having to cache results somewhere. In that call you could run queries and then use their temporary results in your final request. It'll look bit like https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_composite_record_manipulation.htm or https://developer.salesforce.com/blogs/tech-pubs/2017/01/simplify-your-api-code-with-new-composite-resources.html (scroll to the "A Simple Example, Now Using Composite!" part)
{
"compositeRequest" : [{
"method" : "POST",
"url" : "/services/data/v38.0/sobjects/Account",
"referenceId" : "refAccount",
"body" : {
"Name" : "My New Account"
}
},{
"method" : "GET",
"url" : "/services/data/v38.0/query/?q=select+id+from+contact+where+name='Howard+Jones'",
"referenceId" : "refContact"
},{
"method" : "PATCH",
"url" : "/services/data/v38.0/sobjects/Contact/#{refContact.records[0].Id}",
"referenceId" : "refContactUpdated",
"body" : {
"AccountId" : "#{refAccount.id}"
}
}]
}
The downside is that with composite you won't be able to do all 200 in 1 go.
You can have up to 25 subrequests in a single call. Up to 5 of these
subrequests can be sObject Collections or query operations, including
Query and QueryAll requests.

nodejs POST json object which contains array of objects

From client side I am sending object as
{
name: xyz,
data : [
{ k1: v1, k2: v2 },
{ k1: v3, k2: v4 }
]
}
But on server side I am getting it as
{
name: xyz,
data : {
k1: [v1, v3], k2: [v2, v4]
}
}
I am uploading image along with it. Content-type is multipart/form-data
On serverside using body-parser
This looks issue due to ng-upload
{
url: 'url',
method: 'POST',
headers: {'Content-Type': 'multipart/form-data'},
arrayKey: '',
data: {file : $files, data: $data}
}
arrayKey field needed to upload multiple files. Removing it leads to error "Unexpected field" due to issue in ng-upload
But adding above fields causes the issue mention above. Array elements in JSON objects are getting merged.
If field arrayKey is removed, then correct JSON object is received at server side

playlistItems.insert failing in Node.js googleapi youtube

I am uploading a video to Youtube and then attempting to add it to a playlist. The playlist insert is failing in a weird way.
Here is my code:
var options = {
'part' : 'snippet',
'snippet' : {
'playlistId' : playlistId,
'resourceId' : {
'kind' : 'youtube#video',
'videoId' : videoId
}
},
status : {
privacyStatus : 'unlisted'
}
};
console.log('options : ' + JSON.stringify(options));
youtube.playlistItems.insert(options, function(listErr, listResponse){
console.log(JSON.stringify(listErr));
console.log(JSON.stringify(listResponse));
});
I always get the exact same response:
{"errors":[{"domain":"youtube.playlistItem","reason":"playlistIdRequired","message":"Playlist id not specified."}],"code":400,"message":"Playlist id not specified."}
Anyone have any idea what I'm doing wrong? Any help will be much appreciated. I'm using googleapi Node.js sdk.
I was having a similar issue and inspected the source code and realised that the body of an API call should be under options.resource property. So your options object should look like the following:
var options = {
"part" : "snippet",
"resource" : {
"snippet" : {
"playlistId" : playlistId,
"resourceId" : {
"kind" : "youtube#video",
"videoId" : videoId
}
}
}
}
Also note that I've changed the object to use double-quotation marks, as options.resource is expected to be valid JSON. I've also removed the status property as it is not listed as a parameter on the API reference page - https://developers.google.com/youtube/v3/docs/playlistItems/insert

Sharing static card to G+ circles

We have a little nodejs app pushing a static card into the timeline through the Mirror API.
Once received, a Glass user is going to share the card with his or her Google+ circles. It worked quite well until, I think, the XE18.3 update, when the 'Share' Glass menu suddenly stopped showing G+ Circles as an option to share the card with.
Was this a planned modification to the API, and if so, what is considered now a recommended workflow to share a static card with G+ Circles? Or am I just doing something wrong?
Here is a little snipped how the card is created:
$c.google.auth(user.google_tokenRefresh, function (err, token) {
if (err)
return console.log("ERROR #3 in tracks.add at 'get access_token from google' : " + JSON.stringify(err));
require('/node/node_modules/request').post({
url : 'https://www.googleapis.com/upload/mirror/v1/timeline',
qs : {
uploadType : 'multipart'
},
headers : {
'Authorization' : 'Bearer ' + token.access_token
},
multipart : [{
'Content-Type' : 'application/json; charset=UTF-8',
'body' : JSON.stringify({
menuItems : [{
action : 'SHARE'
}, {
action : 'DELETE'
}
]
})
}, {
'Content-Type' : 'image/png',
'body' : buffer
}
]
}, function (err, resp, rdata2) {
console.log(rdata2);
});
});
Thanks!
I think we figured this out: the root of the problem was in the bug #33 (https://code.google.com/p/google-glass-api/issues/detail?id=33&colspec=ID%20Type%20Status%20Priority%20Owner%20Component%20Summary) when a post-processed picture pushed into the timeline through Mirror API does not get published into G+ due to a bug somewhere in Glass code.
Since we did not have in that static card anything else (like a text for example) but a picture, the content was not considered valid to share to G+ Circles.

ExtJs 4 - cross domain policy

I have a simple model:
Ext.define('MovieModel', {
extend : 'Ext.data.Model',
fields : [ {
name : 'Title',
mapping : '#title',
type : 'string'
} ],
proxy : {
type : 'ajax',
url : 'http://www.imdbapi.com/?r=xml&plot=full',
method : 'GET',
reader : {
type : 'xml',
record : 'movie'
}
}
});
But this code doesn't support cross domain policy. How could I solve it?
First of all get rid of r=xml param. Instead of ajax proxy use jsonp one:
proxy : {
type : 'jsonp',
url : 'http://www.imdbapi.com/?plot=full',
// jsonp uses its special method for retrieving data. So no need for the following row
//method : 'GET',
reader : {
type : 'json',
// the record param is used when data is nested construction
// which is not true in your case
//record : 'movie'
}
}
Here is demo.

Resources