Binary file to base64 nodejs - node.js

I'm getting a binary audio file when I call the api tts.speech.microsoft.com and I would like to transform this binary into a base64 string.
I've been trying a lot of things, for example:
Buffer.from(body, "binary").toString("base64");
does not work.
I'm not sure 'binary' is the exact word, but it's not a readable format.
Thank you for your help.

I guess you were following the section Make a request and save the response of the offical document Quickstart: Convert text-to-speech using Node.js to write your code, as below.
var request = require('request');
let options = {
method: 'POST',
baseUrl: 'https://westus.tts.speech.microsoft.com/',
url: 'cognitiveservices/v1',
headers: {
'Authorization': 'Bearer ' + accessToken,
'cache-control': 'no-cache',
'User-Agent': 'YOUR_RESOURCE_NAME',
'X-Microsoft-OutputFormat': 'riff-24khz-16bit-mono-pcm',
'Content-Type': 'application/ssml+xml'
},
body: body
};
function convertText(error, response, body){
if (!error && response.statusCode == 200) {
console.log("Converting text-to-speech. Please hold...\n")
}
else {
throw new Error(error);
}
console.log("Your file is ready.\n")
}
// Pipe the response to file.
request(options, convertText).pipe(fs.createWriteStream('sample.wav'));
So I change the offical code above to create a function encodeWithBase64 to encode body with Base64.
function encodeWithBase64(error, response, body){
if (!error && response.statusCode == 200) {
var strBase64 = Buffer.from(body).toString('base64');
console.log(strBase64);
}
else {
throw new Error(error);
}
console.log("Your file is encoded with Base64.\n")
}
// Pipe the response to file.
request(options, convertText);
Or you can use the npm packages base64-stream and get-stream to get the string with Base64 from body.
var base64 = require('base64-stream');
const getStream = require('get-stream');
(async () => {
var encoder = new base64.Base64Encode();
var b64s = request(options).pipe(encoder);
var strBase64 = await getStream(b64s);
console.log(strBase64);
})();
Otherwise, stream-string also can do it.
var base64 = require('base64-stream');
const ss = require('stream-string');
var encoder = new base64.Base64Encode();
var b64s = request(options).pipe(encoder);
ss(b64s).then(data => {
console.log(data);
})

Related

How to read and save pdf file from response in Node JS client

I have created a Node JS server that pushes the PDF to client as below
app.post("/home", function(req, res, next) {
// to download the file automatically
/*
var file = fs.createReadStream('E:\\test\\conversion\\310-output.pdf');
var stat = fs.statSync('E:\\test\\conversion\\310-output.pdf');
res.setHeader('Content-Length', stat.size);
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename=output.pdf');
file.pipe(res);
*/
// To Stream file to browser
var data =fs.readFileSync('E:\\test\\conversion\\310-output.pdf');
res.contentType("application/pdf");
res.send(data);
});
In client script, i am trying to call above post command and want to fetch the pdf and save it locally from response. Not sure how to do it. Below is client script. In browser, i was able to see the PDF but i need to access it through client script
var request = require('request');
request.post(
'http://localhost:3000/home',
{},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(" Response :: "+response);
// console.log(" Body :: "+body);
}
}
);
To recieve your pdf response in proper format mension "responseType": 'arraybuffer', and "responseEncoding": 'binary' while calling the api
const config = {
baseURL: "<your base url>",
url: "<api endpoint>",
headers: {},
method: "<method>",
responseType: "arraybuffe",
responseEncoding: "binary"
}
let response = await axios(config)
//response.data will be binary encoded buffer Array of pdf data
//*To convert to base64*
var base64 =result.data.toString("base64")
//to convert to binary
var binary =result.data.toString("binary")
//to write to file
fs.writeFileSync(`${name}.pdf`, response.data,'binary');
To download a file by request lib, we will to many ways to do that (I think so!)
Below is a simple way: Create a pipe stream from request response, then save data from stream to a file with a write stream
const request = require('request');
const fs = require('fs');
const req = request.post(
'http://localhost:3000/home',
{},
);
req.on('response', function (res) {
res.pipe(fs.createWriteStream('./filename_to_save.pdf'));
});

How do I convert result from opening gzip file to string

var request = require('request')
request(
{ method: 'GET'
, uri: 'http://www.examplewebsite.com'
, gzip: true
}
, function (error, response, body) {
console.log(body); //I am trying print body here
console.log(response.body); // //I am trying print body here too
}
)
All I received is just �V*.I,)-V�*)*M�QJI,IT��V��,.���%�E��)JV�����d��$1
If I try to use JSON.stringify(body), the result is:
\u001f�\b\u0000\u0000\u0000\u0000\u0000\u0000\u0003�V*.I,)-V�*)*M�QJI,IT��V��,.\u0001��\u0019�\u0005%�E��)JV�����\u0000d��$1\u0000\u0000\u0000
All I want is to see the plain string. How do I do that?
I would expect that setting gzip : true would decompress the response body automatically, but perhaps the server doesn't set the correct Content-Encoding header.
In that case, you can try this:
const zlib = require('zlib');
const request = require('request');
request({
method : 'GET',
uri : 'http://www.examplewebsite.com',
gzip : true,
encoding : null,
}, function (error, response, body) {
let decompressed = zlib.gunzipSync(body).toString();
...
})

calling external rest api from node without encoding querystring params

I am trying to call an external rest API from node server by using request node module.
let request = require('request');
var options = {
method: 'POST',
url: 'https://somerestURI:3000',
qs: { msg: 'some|data|for|other|server' }
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
If I try to run the above code, query string value is being encoded to
some%7cdata%7cfor%7cother%7cserver
as a result I am not receiving correct response.
But if I fire the same request in POSTMAN. I am receiving the expected output(I think postman is not encoding query string).
So what I want is don't encode the query string value.
Any help would be greatly appreciated.
As answered here, you can disable encoding in qsStringifyOptions
var options = {
method: 'POST',
url: 'https://somerestURI:3000',
qs: { msg: 'some|data|for|other|server' },
qsStringifyOptions: {
encoding: false
}
};
You can use node-rest-client package. It allows connecting to any REST API and get results as javascript Object.
var HttpClient = require('node-rest-client').Client;
var httpClient = new HttpClient();
// GET Call
httpClient.get("http://remote.site/rest/xml/method", function (data, response) {
// parsed response body as js object
console.log(data);
// raw response
console.log(response);
});)
or for POST Call
var args = {
data: { test: "hello" },
headers: { "Content-Type": "application/json" }
};
//POST Call
httpClient.post("http://remote.site/rest/xml/method", args, function (data, response) {
// parsed response body as js object
console.log(data);
// raw response
console.log(response);
});

nodejs set encoding of body using request module

I have to send a post request with a body containing russian characters to a service which seems to only accept win1251 encoding. I am doing this in node.js using the request module.
This is how I am sending the request
var rawbody = "i1=&i2=&i3=" + query + "&i4=&i5=&i8=";
var options = {
url: this.initiate_endpoint,
jar: this.session,
cert: this.fs.readFileSync('resources/r.crt.pem', 'utf-8'),
key: this.fs.readFileSync('resources/r.key.pem', 'utf-8'),
timeout: 20000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: rawbody
};
let cookie = this.session;
request.post(options,
function (error, response, body) {
if( error ) {
callback(cookie, error);
}
else if( response.statusCode !== 200 ) {
callback(cookie, 'Responded with status code: ' + response.statusCode);
}
else {
callback(cookie, false);
}
});
Whenever the query variable is containing russian letters the request will fail.
For example:
var query = 'Путин';
So my questions are how to actually convert the encoding from the query variable to win1251 and furthermore how to set the encoding of the actual raw postbody, because I think those two things could be the cause of the issue.

Uploading file using POST request in Node.js

I have problem uploading file using POST request in Node.js. I have to use request module to accomplish that (no external npms). Server needs it to be multipart request with the file field containing file's data. What seems to be easy it's pretty hard to do in Node.js without using any external module.
I've tried using this example but without success:
request.post({
uri: url,
method: 'POST',
multipart: [{
body: '<FILE_DATA>'
}]
}, function (err, resp, body) {
if (err) {
console.log('Error!');
} else {
console.log('URL: ' + body);
}
});
Looks like you're already using request module.
in this case all you need to post multipart/form-data is to use its form feature:
var req = request.post(url, function (err, resp, body) {
if (err) {
console.log('Error!');
} else {
console.log('URL: ' + body);
}
});
var form = req.form();
form.append('file', '<FILE_DATA>', {
filename: 'myfile.txt',
contentType: 'text/plain'
});
but if you want to post some existing file from your file system, then you may simply pass it as a readable stream:
form.append('file', fs.createReadStream(filepath));
request will extract all related metadata by itself.
For more information on posting multipart/form-data see node-form-data module, which is internally used by request.
An undocumented feature of the formData field that request implements is the ability to pass options to the form-data module it uses:
request({
url: 'http://example.com',
method: 'POST',
formData: {
'regularField': 'someValue',
'regularFile': someFileStream,
'customBufferFile': {
value: fileBufferData,
options: {
filename: 'myfile.bin'
}
}
}
}, handleResponse);
This is useful if you need to avoid calling requestObj.form() but need to upload a buffer as a file. The form-data module also accepts contentType (the MIME type) and knownLength options.
This change was added in October 2014 (so 2 months after this question was asked), so it should be safe to use now (in 2017+). This equates to version v2.46.0 or above of request.
Leonid Beschastny's answer works but I also had to convert ArrayBuffer to Buffer that is used in the Node's request module. After uploading file to the server I had it in the same format that comes from the HTML5 FileAPI (I'm using Meteor). Full code below - maybe it will be helpful for others.
function toBuffer(ab) {
var buffer = new Buffer(ab.byteLength);
var view = new Uint8Array(ab);
for (var i = 0; i < buffer.length; ++i) {
buffer[i] = view[i];
}
return buffer;
}
var req = request.post(url, function (err, resp, body) {
if (err) {
console.log('Error!');
} else {
console.log('URL: ' + body);
}
});
var form = req.form();
form.append('file', toBuffer(file.data), {
filename: file.name,
contentType: file.type
});
You can also use the "custom options" support from the request library. This format allows you to create a multi-part form upload, but with a combined entry for both the file and extra form information, like filename or content-type. I have found that some libraries expect to receive file uploads using this format, specifically libraries like multer.
This approach is officially documented in the forms section of the request docs - https://github.com/request/request#forms
//toUpload is the name of the input file: <input type="file" name="toUpload">
let fileToUpload = req.file;
let formData = {
toUpload: {
value: fs.createReadStream(path.join(__dirname, '..', '..','upload', fileToUpload.filename)),
options: {
filename: fileToUpload.originalname,
contentType: fileToUpload.mimeType
}
}
};
let options = {
url: url,
method: 'POST',
formData: formData
}
request(options, function (err, resp, body) {
if (err)
cb(err);
if (!err && resp.statusCode == 200) {
cb(null, body);
}
});
I did it like this:
// Open file as a readable stream
const fileStream = fs.createReadStream('./my-file.ext');
const form = new FormData();
// Pass file stream directly to form
form.append('my file', fileStream, 'my-file.ext');
const remoteReq = request({
method: 'POST',
uri: 'http://host.com/api/upload',
headers: {
'Authorization': 'Bearer ' + req.query.token,
'Content-Type': req.headers['content-type'] || 'multipart/form-data;'
}
})
req.pipe(remoteReq);
remoteReq.pipe(res);

Resources