Node.js - assign writable stream to a variable - javascript

As in below code, I can write base64 encoded stream into a file but I want to assign the base64 encoded string to a variable rather than creating a file so that I can use it for the purpose I want. How can I assign response.pipe(base64.encode()); to a variable as base64 encoded string ? I am using base64-stream to encode incoming stream.
const request = xero.call('GET', `/Invoices/${invoiceId}`);
request.setHeader('Accept', 'application/pdf');
request.on('response', async (response) => {
const data = response.pipe(base64.encode());
const file = fs.createWriteStream(`${invoiceId}.txt`);
data.pipe(file);
});
request.end();

To store the contents of the stream as a string you need to concatenate the base64 stream and then store that buffer as a variable. For that I like to use concat-stream.
keep the stream around with const data = response.pipe(base64.encode());
but then
data.pipe(concat(buf => {
const str = buf.toString('base64')
})

Related

Base64 to Image File Convertion in JS

I am working on a project where I have to upload an image as form data along with other text fields. I have my file in Base64 string at first, then I convert it into a file before uploading it to the server.
const data = await fetch(base64String);
const blob = await data.blob();
const file = await new File([blob], 'avatar', { type: 'image/png' });
I logged the base64String in the client side before uploading it to the server. Then I upload file to the server as a File. Before saving it to MongoDB when I log it as a base64 string again in the server side, I see my string is not the same as before. I feel like while converting the base64 to file in the client side I am doing something wrong. Help me out please.
I have figured out my problem. When I take image file input from my computer I get a base64 string like below -
dataimage/jpegbase64/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA...
But, when I convert it back into a file it expects a string like below -
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA....
So, basically, I had to trim the string accordingly to match the expected format and wrote a base64 to file conversion function following this answer.
Here is my function to convert a base64 string to an image file
export function getFileFromBase64(string64:string, fileName:string) {
const trimmedString = string64.replace('dataimage/jpegbase64', '');
const imageContent = atob(trimmedString);
const buffer = new ArrayBuffer(imageContent.length);
const view = new Uint8Array(buffer);
for (let n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
const type = 'image/jpeg';
const blob = new Blob([buffer], { type });
return new File([blob], fileName, { lastModified: new Date().getTime(), type });
}

PublicKeyCredential not possible to serialize

I am implementing FIDO2(WebAuthn) in a Angular application.
I have gotten the PublicKeyCredentialCreationOptions object and seccessfullt register.
But after calling
let response = await navigator.credentials.create({'publicKey': myPublicKeyCredentialCreationOption })
I try to send the response to the server.. But this fails.
When I tried to look at the object in the browser using
console.log(JSON.stringify(response))
I get
{}
as output (?..) but when doing
console.log(response)
I get a object with values in the console...
How should the object get serialized to send to the server?
PublicKeyCredential objects contains ArrayBuffer objects that cannot be serialized as JSON. You could base64 encode these values in your Angular app and decode on the server to get the same byte array back. A helper library to do exactly that for WebAuthn exists: https://github.com/github/webauthn-json
Here's a very simple example for anyone who needs it:
function bufferToBase64url (buffer) {
// modified from https://github.com/github/webauthn-json/blob/main/src/webauthn-json/base64url.ts
const byteView = new Uint8Array(buffer);
let str = "";
for (const charCode of byteView) {
str += String.fromCharCode(charCode);
}
// Binary string to base64
const base64String = btoa(str);
// Base64 to base64url
// We assume that the base64url string is well-formed.
const base64urlString = base64String.replace(/\+/g, "-").replace(
/\//g,
"_",
).replace(/=/g, "");
return base64urlString;
}
...
create publicKeyCredentialCreationOptions
...
navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
}).then(credential => {
// credential created
// console.log(credential); <-- check what is output to see what you need to call bufferToBase64url(credential.<...>) on down below
// convert credential to json serializeable
const serializeable = {
authenticatorAttachment: credential.authenticatorAttachment,
id: credential.id,
rawId: bufferToBase64url(credential.rawId),
response: {
attestationObject: bufferToBase64url(credential.response.attestationObject),
clientDataJSON: bufferToBase64url(credential.response.clientDataJSON)
},
type: credential.type
};
const serialized = JSON.stringify(serializeable);
console.log(serialized);
}).catch(err => {
// an error occurred
console.error(err);
});

Not returning anything base64 decode

I try to decrypt a file with crypto-js (in this file there is a long string of encrypted base64).
but I don't get anything back the file is empty and the log too.
const fs = require("fs");
const CryptoJS = require("crypto-js");
fs.writeFile("2pac.txt", decode(), (err) => {
if (err) throw err;
// success case, the file was saved
console.log("Lyric saved!");
});
function decode() {
// INIT
const encoded = fs.readFileSync("./base64.txt", { encoding: "base64" });
// PROCESS
const decoded = CryptoJS.enc.Utf8.stringify(encoded); // decode encodedWord via Utf8.stringify() '75322541'
console.log(decoded);
return decoded;
}
In the console.log I get the test but I don't get anything(even undefined).
Replace this line:
const decoded = CryptoJS.enc.Utf8.stringify(encoded);
with:
const decoded = CryptoJS.enc.Utf8.stringify(CryptoJS.enc.Base64.parse(encoded));
EDIT:
Reading base64 data from file is another problem. The data imported from the file with the encoding option set to base64 does guarantee a string instead of a buffer but it expects the input to be utf-8 encoding the base64 string again (double encoding).
To fix this, change the following:
const encoded = fs.readFileSync("./base64.txt", { encoding: "base64" });
to:
const encoded = fs.readFileSync("./base64.txt").toString();

How to read remote image to a base64 data url

actually there are many answers for this question. But my problem is,
i want to generate pdf dynamically with 5 external(URL) images. Im using PDFmake node module.
it supports only two ways local and base64 format. But i don't want to store images locally.
so my requirement is one function which takes url as parameter and returns base64.
so that i can store in global variable and create pdfs
thanks in advance
function urlToBase(URL){
return base64;
}
var img = urlToBase('https://unsplash.com/photos/MVx3Y17umaE');
var dd = {
content: [
{
text: 'fjfajhal'
},
{
image: img,
}
]
};
var writeStream = fs.createWriteStream('myPdf.pdf');
var pdfDoc = printer.createPdfKitDocument(dd);
pdfDoc.pipe(writeStream);
pdfDoc.end();
im using PDFmake module from npm
The contents of the remote image can first be fetched with an HTTP request, for example using the ubiquitous request npm module. The image string contents can then be transformed to a buffer and finally converted to a base64 string. To complete the transformation, add the proper data-url prefix, for example, data:image/png,base64, to the beginning of the base64 string.
Here is a rough example for a PNG image:
const request = require('request-promise-native');
let jpgDataUrlPrefix = 'data:image/png;base64,';
let imageUrl = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';
request({
url: imageUrl,
method: 'GET',
encoding: null // This is actually important, or the image string will be encoded to the default encoding
})
.then(result => {
let imageBuffer = Buffer.from(result);
let imageBase64 = imageBuffer.toString('base64');
let imageDataUrl = jpgDataUrlPrefix+imageBase64;
console.log(imageDataUrl);
});

Create data URIs on the fly?

Is there a script (javascript / client side). That create data URIs on the fly. Now i create data URIs with a online base64 creator. And then put that output in the css file. But when i changing the images. Its a lot of work to do it. Is there a script, that can do it for me.?
The modern browsers now have good support for base64 encoding and decoding. There are two functions respectively for decoding and encoding base64 strings:
atob() decodes a string of base-64 data
btoa() creates a base-64 encoded ASCII string from a "string" of binary data
This let's you create data uri's easily i.e
var longText = "Lorem ipsum....";
var dataUri = "data:text/plain;base64," + btoa(longText);
//a sample api expecting an uri
d3.csv(dataUri, function(parsed){
});
As a complete solution to your scenario, you can use fetch to get a blob representation of your image, and then use FileReader to convert the blob in its base64 representation
// get an image blob from url using fetch
let getImageBlob = function(url){
return new Promise( async resolve=>{
let resposne = await fetch( url );
let blob = resposne.blob();
resolve( blob );
});
};
// convert a blob to base64
let blobToBase64 = function(blob) {
return new Promise( resolve=>{
let reader = new FileReader();
reader.onload = function() {
let dataUrl = reader.result;
resolve(dataUrl);
};
reader.readAsDataURL(blob);
});
}
// combine the previous two functions to return a base64 encode image from url
let getBase64Image = async function( url ){
let blob = await getImageBlob( url );
let base64 = await blobToBase64( blob );
return base64;
}
// test time!
getBase64Image( 'http://placekitten.com/g/200/300' ).then( base64Image=> console.log( base64Image) );
One way is to make a Blob of an object, and then use URL.createObjectURL()
let a = URL.createObjectURL(new Blob([JSON.stringify({whatever: "String..."}, null, 2)]))
console.log(a)

Categories

Resources