NodeJS: Download File and convert to binary string - javascript

I am pretty new to Node.js and struggle with current topic:
I am calling an API which returns me a file (audio.amr). I now need to convert this file during runtime, without saving it, to a binary string in order to pass it further.
I tried passing the received object to the "fs" module, but without any luck.
requestify.request('https://some-url.com', {
method: 'GET'
}).then(function (response) { var obj = response.getBody() }
In "obj" is now a file returned that I need to convert to a binary string.

You can use an ArrayBuffer to hold binary data, then convert the ArrayBuffer to a Hex string. To get the raw body from requestify, you'll have to use the .body property instead of the getBody() function, according to their documentation.
You'll have to check what the raw body's type is and convert it to an ArrayBuffer if necessary.
// ...
var obj = response.body; // Get the raw body
var arrayBuffer = new TextEncoder().encode (obj); // Convert String data to ArrayBuffer (might need to be changed)
var hexString = bufferToHex (arrayBuffer);
// ...
function bufferToHex (buffer) {
return Array
.from (new Uint8Array (buffer))
.map (b => b.toString (16).padStart (2, "0"))
.join ("");
}
Update:
Since apparently requestify has no way to handle raw body data, I suggest you use node-fetch, a window.fetch polyfill for nodeJS.
Your code with it would look as follows:
const fetch = require ("node-fetch");
fetch(yourUrl, {
method: 'GET'
}).then(function (response) {
return response.arrayBuffer ();
}).then(function (arrayBuf) {
const hexString = bufferToHex (arrayBuf);
// Do whatever you want
});

Related

Decoding payload with JavaScript

i need some support in parsing a payload with javascript. Below you see the json body. I need to return only the valuetype "occupants".
{"id":"8684bc99-5a69-4b7a-92c2-69faa91b668b","type":"airthings-webhook-cloudevent-occupancy-ventilation-sample-feed","source":"https://dashboard.airthings.com/integrations/webhooks/2c823594-3c4b-4352-9929-8486a5f8a985","dataContentType":"application/json","labels":{},"data":[{"measurementSystem":"METRIC","serialNumber":"2930118961","recorded":"2022-05-04T08:55:00","occupants":4.0,"ventilationAmount":171.0,"ventilationState":true,"ratings":{},"sensorUnits":{"occupants":"occ","ventilationAmount":"m3h","relativeVentilationRate":"ach"}}],"time":"2022-05-04T08:58:20.322709","specVersion":"0.2"}
I made it to return the "data" array with the following decoder. Now i need the object "occupants" within data. Can someone tell me what I need to adjust in the following code?
function Decoder(request) {
// Parse JSON into Object
var payload = JSON.parse(request.body);
// Load Data from JSON
var data = payload.data;
var Occupancy = data.occupants;
//var humidity = data.hum;
//var battery = data.bat;
// Forward Data into Device using Serial
return data;
}

How can I set query string in fetchAPI [duplicate]

I'm trying to use the new Fetch API:
I am making a GET request like this:
var request = new Request({
url: 'http://myapi.com/orders',
method: 'GET'
});
fetch(request);
However, I'm unsure how to add a query string to the GET request. Ideally, I want to be able to make a GET request to a URL like:
'http://myapi.com/orders?order_id=1'
In jQuery I could do this by passing {order_id: 1} as the data parameter of $.ajax(). Is there an equivalent way to do that with the new Fetch API?
A concise, modern approach:
fetch('https://example.com?' + new URLSearchParams({
foo: 'value',
bar: 2,
}))
How it works: When a string (e.g. the URL) is being concatenated with an instance of URLSearchParams, its toString() method will automatically be called to convert the instance into a string representation, which happens to be a properly encoded query string. If the automatic invoking of toString() is too magical for your liking, you may prefer to explicitly call it like so: fetch('https://...' + new URLSearchParams(...).toString())
A complete example of a fetch request with query parameters:
// Real example you can copy-paste and play with.
// jsonplaceholder.typicode.com provides a dummy rest-api
// for this sort of purpose.
async function doAsyncTask() {
const url = (
'https://jsonplaceholder.typicode.com/comments?' +
new URLSearchParams({ postId: 1 }).toString()
);
const result = await fetch(url)
.then(response => response.json());
console.log('Fetched from: ' + url);
console.log(result);
}
doAsyncTask();
If you are using/supporting...
IE: Internet Explorer does not provide native support for URLSearchParams or fetch, but there are polyfills available.
Node: As of Node 18 there is native support for the fetch API (in version 17.5 it was behind the --experimental-fetch flag). In older versions, you can add the fetch API through a package like node-fetch. URLSearchParams comes with Node, and can be found as a global object since version 10. In older version you can find it at require('url').URLSearchParams.
Node + TypeScript: If you're using Node and TypeScript together you'll find that, due to some technical limitations, TypeScript does not offer type definitions for the global URLSearchParams. The simplest workaround is to just import it from the url module. See here for more info.
Update March 2017:
URL.searchParams support has officially landed in Chrome 51, but other browsers still require a polyfill.
The official way to work with query parameters is just to add them onto the URL. From the spec, this is an example:
var url = new URL("https://geo.example.org/api"),
params = {lat:35.696233, long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url).then(/* … */)
However, I'm not sure Chrome supports the searchParams property of a URL (at the time of writing) so you might want to either use a third party library or roll-your-own solution.
Update April 2018:
With the use of URLSearchParams constructor you could assign a 2D array or a object and just assign that to the url.search instead of looping over all keys and append them
var url = new URL('https://sl.se')
var params = {lat:35.696233, long:139.570431} // or:
var params = [['lat', '35.696233'], ['long', '139.570431']]
url.search = new URLSearchParams(params).toString();
fetch(url)
Sidenote: URLSearchParams is also available in NodeJS
const { URL, URLSearchParams } = require('url');
let params = {
"param1": "value1",
"param2": "value2"
};
let query = Object.keys(params)
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
.join('&');
let url = 'https://example.com/search?' + query;
fetch(url)
.then(data => data.text())
.then((text) => {
console.log('request succeeded with JSON response', text)
}).catch(function (error) {
console.log('request failed', error)
});
As already answered, this is per spec not possible with the fetch-API, yet. But I have to note:
If you are on node, there's the querystring package. It can stringify/parse objects/querystrings:
var querystring = require('querystring')
var data = { key: 'value' }
querystring.stringify(data) // => 'key=value'
...then just append it to the url to request.
However, the problem with the above is, that you always have to prepend a question mark (?). So, another way is to use the parse method from nodes url package and do it as follows:
var url = require('url')
var data = { key: 'value' }
url.format({ query: data }) // => '?key=value'
See query at https://nodejs.org/api/url.html#url_url_format_urlobj
This is possible, as it does internally just this:
search = obj.search || (
obj.query && ('?' + (
typeof(obj.query) === 'object' ?
querystring.stringify(obj.query) :
String(obj.query)
))
) || ''
You can use stringify from query-string.
import { stringify } from 'query-string';
fetch(`https://example.org?${stringify(params)}`)
encodeQueryString — encode an object as querystring parameters
/**
* Encode an object as url query string parameters
* - includes the leading "?" prefix
* - example input — {key: "value", alpha: "beta"}
* - example output — output "?key=value&alpha=beta"
* - returns empty string when given an empty object
*/
function encodeQueryString(params) {
const keys = Object.keys(params)
return keys.length
? "?" + keys
.map(key => encodeURIComponent(key)
+ "=" + encodeURIComponent(params[key]))
.join("&")
: ""
}
encodeQueryString({key: "value", alpha: "beta"})
//> "?key=value&alpha=beta"
I know this is stating the absolute obvious, but I feel it's worth adding this as an answer as it's the simplest of all:
const orderId = 1;
fetch('http://myapi.com/orders?order_id=' + orderId);
Maybe this is better:
const withQuery = require('with-query');
fetch(withQuery('https://api.github.com/search/repositories', {
q: 'query',
sort: 'stars',
order: 'asc',
}))
.then(res => res.json())
.then((json) => {
console.info(json);
})
.catch((err) => {
console.error(err);
});
Solution without external packages
to perform a GET request using the fetch api I worked on this solution that doesn't require the installation of packages.
this is an example of a call to the google's map api
// encode to scape spaces
const esc = encodeURIComponent;
const url = 'https://maps.googleapis.com/maps/api/geocode/json?';
const params = {
key: "asdkfñlaskdGE",
address: "evergreen avenue",
city: "New York"
};
// this line takes the params object and builds the query string
const query = Object.keys(params).map(k => `${esc(k)}=${esc(params[k])}`).join('&')
const res = await fetch(url+query);
const googleResponse = await res.json()
feel free to copy this code and paste it on the console to see how it works!!
the generated url is something like:
https://maps.googleapis.com/maps/api/geocode/json?key=asdkf%C3%B1laskdGE&address=evergreen%20avenue&city=New%20York
this is what I was looking before I decided to write this, enjoy :D
Template literals are also a valid option here, and provide a few benefits.
You can include raw strings, numbers, boolean values, etc:
let request = new Request(`https://example.com/?name=${'Patrick'}&number=${1}`);
You can include variables:
let request = new Request(`https://example.com/?name=${nameParam}`);
You can include logic and functions:
let request = new Request(`https://example.com/?name=${nameParam !== undefined ? nameParam : getDefaultName() }`);
As far as structuring the data of a larger query string, I like using an array concatenated to a string. I find it easier to understand than some of the other methods:
let queryString = [
`param1=${getParam(1)}`,
`param2=${getParam(2)}`,
`param3=${getParam(3)}`,
].join('&');
let request = new Request(`https://example.com/?${queryString}`, {
method: 'GET'
});
Was just working with Nativescript's fetchModule and figured out my own solution using string manipulation.
Append the query string bit by bit to the url. Here is an example where query is passed as a json object (query = {order_id: 1}):
function performGetHttpRequest(fetchLink='http://myapi.com/orders', query=null) {
if(query) {
fetchLink += '?';
let count = 0;
const queryLength = Object.keys(query).length;
for(let key in query) {
fetchLink += key+'='+query[key];
fetchLink += (count < queryLength) ? '&' : '';
count++;
}
}
// link becomes: 'http://myapi.com/orders?order_id=1'
// Then, use fetch as in MDN and simply pass this fetchLink as the url.
}
I tested this over a multiple number of query parameters and it worked like a charm :)
Hope this helps someone.
var paramsdate=01+'%s'+12+'%s'+2012+'%s';
request.get("https://www.exampleurl.com?fromDate="+paramsDate;

Angular 2 - Http Get request - pass json Object

How can I do a http get request and pass an json Object
This is my json-Object
{{firstname:"Peter", lastname:"Test"}
and this Object I want to pass in the http request to get a list Of matched persons.
how is it possible? This example just shows a simple get request with a json result. How do I have to modify it?
//Component:
person:Person;
persons:Person [];
....
//Whre can I pass the person, here in the service??
getMatchedPersons(){
this.httpService.getMatchedPersons().subscribe(
data => this.persons = data,
error => aller(error)
);
);
//SERVICE
//pass parameters?? how to send the person object here?
getMatchedPersons(){
return this.http.get('url').map(res => res.json());
}
The Http.get method takes an object that implements RequestOptionsArgs as a second parameter.
The search field of that object can be used to set a string or a URLSearchParams object.
An example:
// Parameters obj-
let params: URLSearchParams = new URLSearchParams();
params.set('firstname', yourFirstNameData);
params.set('lastname', yourLastNameData);
//Http request-
return this.http.get('url', {
search: params
}).subscribe(
(response) => //some manipulation with response
);
For pure javascript:
You must serialize your json to a list of parameters:
?firstname=peter&lastname=test
and append it to the URL because GET requests have no body.
There are a few ways of converting JSON to QueryParameters.
They are addressed in this question: Is there any native function to convert json to url parameters?
There you can choose the poison of your liking, mine was:
function obj_to_query(obj) {
var parts = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
}
return "?" + parts.join('&');
}
But mind you that GET requests must obbey the URL limit that based on this answer is recomended to stay under 2000 characters to be safe:
RFC says 8000
IE8 and IE9 go as far as 2083
Search engines only read to 2048
Using Angular2 URLSearchParams
With the same method of converting a plain JSON to arguments one could use URLSearchParams as suggested by Рома Скидан:
let params: URLSearchParams = objToSearchParams(obj);
return this.http.get('url', {
search: params
}).subscribe(
(response) => //some manipulation with response
);
function objToSearchParams(obj): URLSearchParams{
let params: URLSearchParams = new URLSearchParams();
for (var key in obj) {
if (obj.hasOwnProperty(key))
params.set(key, obj[key]);
}
return params;
}
Maybe you want to stringify the json object
var json = JSON.stringify(myObj);
this.http.get('url'+'?myobj='+encodeURIComponent(json))
Use a POST request to pass objects to the server:
//SERVICE
getMatchedPersons(searchObj: any){
return this.http.post('url', JSON.stringify(searchObj))
.map(res => res.json());
}
Then you can pass whatever JS object you want and send it to the server in your http request.
getMatchedPersons(searchObj: any){
this.httpService.getMatchedPersons(searchObj: any).subscribe(
data => this.persons = data,
error => alert(error);
);
);
Similar to AngJobs' but maybe more up-to-date?? Calling encodeURIComponent is not necessary. Here's the Angular:
const stringifiedParams = JSON.stringify(this.filterParams);
return this.http.get<any[]>(`persons`, {params: {filter: stringifiedParams}});
On the server Node deserializes the params with JSON.parse:
filter = JSON.parse(req.query.filter.toString());
Actually there's an easier way for flushing parameters
getMatchedPersons(myObject: any): Observable<Person[]> {
return this.http.get<Person[]>('url', { params: { ...myObject } });
}
The above code represents a function that accepts a JSON object myObject as a parameter.
HttpClient.get method accepts an options paramter as its second paramter.
The options parameter contains many useful keys, but we're only interested with the params key in our case.
the value of params is { ...myObject }, that is- we're using the spread operator to pass all key:value pairs from an object.
Refer that this will do the job, and will not make the URL look ugly with all those ? and key=value and & characters, of course in either case those parameters won't be shown for the user since it's just an HTTP call, but still, if anyone is using a logger interceptor, they will have a clean log.

How to serialize File object to JSON? [duplicate]

I want to convert an HTML input file to a JSON string like this:
var jsonString = JSON.stringify(file);
console.log( file );
console.log( jsonString );
Now, in my Firebug it logs as:
File { size=360195, type="image/jpeg", name="xyz.jpg", mehr...}
Object {}
Why is the jsonString empty?
Background info: I want to send the file-reference with JSONP to another PHP server.
Additional Information: I want to convert only the file-pointer (reference) to a string, to send it via GET.
It is not possible to directly convert a File object into JSON using JSON.stringify in Chrome, Firefox and Safari.
You can make a work around to convert File object to string using JSON.stringify
Ex:
// get File Object
var fileObject = getFile();
// reCreate new Object and set File Data into it
var newObject = {
'lastModified' : fileObject.lastModified,
'lastModifiedDate' : fileObject.lastModifiedDate,
'name' : fileObject.name,
'size' : fileObject.size,
'type' : fileObject.type
};
// then use JSON.stringify on new object
JSON.stringify(newObject);
You can also add the toJSON() behavior to your File object
EX:
// get File Object
var fileObject = getFile();
// implement toJSON() behavior
fileObject.toJSON = function() { return {
'lastModified' : myFile.lastModified,
'lastModifiedDate' : myFile.lastModifiedDate,
'name' : myFile.name,
'size' : myFile.size,
'type' : myFile.type
};}
// then use JSON.stringify on File object
JSON.stringify(fileObject);
Note: send a File Object to server using the POST HTTP method.
You have to read the file content using the FileReader API. The File object does not contain the file content (it is just a pointer toward the file, which allows you to read it later).
You can check out this HTML5Rocks article to find out more about the usage of this API.
var file = getAFile( );
var success = function ( content ) {
console.log( JSON.stringify( content ) ); }
var fileReader = new FileReader( );
fileReader.onload = function ( evt ) { success( evt.target.result ) };
fileReader.readAsText( file );
In case anyone is still looking for a solution to this please see my answer on a different post and working example on JSFiddle.
JS:
function getFiles(){
var files = document.getElementById("myFiles").files;
var myArray = [];
var file = {};
console.log(files); // see the FileList
// manually create a new file obj for each File in the FileList
for(var i = 0; i < files.length; i++){
file = {
'lastMod' : files[i].lastModified,
'lastModDate': files[i].lastModifiedDate,
'name' : files[i].name,
'size' : files[i].size,
'type' : files[i].type,
}
//add the file obj to your array
myArray.push(file)
}
//stringify array
console.log(JSON.stringify(myArray));
}
HTML:
<input id="myFiles" type="file" multiple onchange="getFiles()" />
You just need a custom replacer:
function stringify(obj) {
const replacer = [];
for (const key in obj) {
replacer.push(key);
}
return JSON.stringify(obj, replacer);
}
const json = stringify(file);
console.log(file);
console.log(json);
Now you should see:
File {name: "xyz.jpg", type: "image/jpeg", size...}
'{"name":"xyz.jpg","type":"image/jpeg","size"...}'
Instead of looping through, or rather extracting each key one after the other, i came up with this function and i've used it image input.
const fileObject = e.target.files[0];
important notice
//dont use shorthand for of loop
for (const [key, value] in Object.entries(x))
it can't loop through a file object in JS
Use this code instead
const imageObject = {};
for (const key in fileObject) {
const value = fileObject[key];
const notFunction = typeof value !== "function";
notFunction && (imageObject[key] = value);
}
console.log(imageObject) // => should give you a normal JS object now
When you pass a json string Javascript internally trnsform it to Json object and hence no need to parse it.
follow steps in case of of json file ->
$('#inp_import_template')[0].files[0]
Now your json file is transformed to json object (Javascript).
var obj = {
name: 'dashu3f'
};
var stringObj = JSON.stringify(obj);
console.log(typeof stringObj);
console.log(stringObj);
open terminal this Folder file and run node json.js

How can I serialize an input File object to JSON?

I want to convert an HTML input file to a JSON string like this:
var jsonString = JSON.stringify(file);
console.log( file );
console.log( jsonString );
Now, in my Firebug it logs as:
File { size=360195, type="image/jpeg", name="xyz.jpg", mehr...}
Object {}
Why is the jsonString empty?
Background info: I want to send the file-reference with JSONP to another PHP server.
Additional Information: I want to convert only the file-pointer (reference) to a string, to send it via GET.
It is not possible to directly convert a File object into JSON using JSON.stringify in Chrome, Firefox and Safari.
You can make a work around to convert File object to string using JSON.stringify
Ex:
// get File Object
var fileObject = getFile();
// reCreate new Object and set File Data into it
var newObject = {
'lastModified' : fileObject.lastModified,
'lastModifiedDate' : fileObject.lastModifiedDate,
'name' : fileObject.name,
'size' : fileObject.size,
'type' : fileObject.type
};
// then use JSON.stringify on new object
JSON.stringify(newObject);
You can also add the toJSON() behavior to your File object
EX:
// get File Object
var fileObject = getFile();
// implement toJSON() behavior
fileObject.toJSON = function() { return {
'lastModified' : myFile.lastModified,
'lastModifiedDate' : myFile.lastModifiedDate,
'name' : myFile.name,
'size' : myFile.size,
'type' : myFile.type
};}
// then use JSON.stringify on File object
JSON.stringify(fileObject);
Note: send a File Object to server using the POST HTTP method.
You have to read the file content using the FileReader API. The File object does not contain the file content (it is just a pointer toward the file, which allows you to read it later).
You can check out this HTML5Rocks article to find out more about the usage of this API.
var file = getAFile( );
var success = function ( content ) {
console.log( JSON.stringify( content ) ); }
var fileReader = new FileReader( );
fileReader.onload = function ( evt ) { success( evt.target.result ) };
fileReader.readAsText( file );
In case anyone is still looking for a solution to this please see my answer on a different post and working example on JSFiddle.
JS:
function getFiles(){
var files = document.getElementById("myFiles").files;
var myArray = [];
var file = {};
console.log(files); // see the FileList
// manually create a new file obj for each File in the FileList
for(var i = 0; i < files.length; i++){
file = {
'lastMod' : files[i].lastModified,
'lastModDate': files[i].lastModifiedDate,
'name' : files[i].name,
'size' : files[i].size,
'type' : files[i].type,
}
//add the file obj to your array
myArray.push(file)
}
//stringify array
console.log(JSON.stringify(myArray));
}
HTML:
<input id="myFiles" type="file" multiple onchange="getFiles()" />
You just need a custom replacer:
function stringify(obj) {
const replacer = [];
for (const key in obj) {
replacer.push(key);
}
return JSON.stringify(obj, replacer);
}
const json = stringify(file);
console.log(file);
console.log(json);
Now you should see:
File {name: "xyz.jpg", type: "image/jpeg", size...}
'{"name":"xyz.jpg","type":"image/jpeg","size"...}'
Instead of looping through, or rather extracting each key one after the other, i came up with this function and i've used it image input.
const fileObject = e.target.files[0];
important notice
//dont use shorthand for of loop
for (const [key, value] in Object.entries(x))
it can't loop through a file object in JS
Use this code instead
const imageObject = {};
for (const key in fileObject) {
const value = fileObject[key];
const notFunction = typeof value !== "function";
notFunction && (imageObject[key] = value);
}
console.log(imageObject) // => should give you a normal JS object now
When you pass a json string Javascript internally trnsform it to Json object and hence no need to parse it.
follow steps in case of of json file ->
$('#inp_import_template')[0].files[0]
Now your json file is transformed to json object (Javascript).
var obj = {
name: 'dashu3f'
};
var stringObj = JSON.stringify(obj);
console.log(typeof stringObj);
console.log(stringObj);
open terminal this Folder file and run node json.js

Categories

Resources