Data URI to JSON in Javascript? - javascript

I am facing a problem where my server app gets a JSON's DataURI and I would like to parse it into a JSON again. How could I do this? I tried different things but nothings seems to work. I tried simply parsing it or encodeURI(data); but still I can't get the original JSON.
This is the Data URI:
data:application/json;base64,ew0KICAgICJtYWx0X3R5cGUiOiAibG9nIiwNCiAgICAibWFsdF9kYXRhIjogIldvdywgdSByIGFsbW9zdCB0aGVyZSA6TyINCn0=
I tried this to encode it too:
var data = 'data:application/json;base64,ew0KICAgICJtYWx0X3R5cGUiOiAibG9nIiwNCiAgICAibWFsdF9kYXRhIjogIldvdywgdSByIGFsbW9zdCB0aGVyZSA6TyINCn0=';
Buffer.from(data.toString('utf8'), 'base64').toString('ascii')
But I get this if I log it on console: u+Zje F- J'm+k0P"&VGEwGR#"&Fvr"#P"&VGEvFF#"%vwrBR"FVw7BFW&R$r P'

The data URI is JSON encoded in Base64. There are two steps to this:
Decode the Base64 (for instance, with the atob function), and
Parse the resulting JSON
For instance (on a browser):
const dataURI = "data:application/json;base64,ew0KICAgICJtYWx0X3R5cGUiOiAibG9nIiwNCiAgICAibWFsdF9kYXRhIjogIldvdywgdSByIGFsbW9zdCB0aGVyZSA6TyINCn0=";
// 29 = length of "data:application/json;base64,"
const json = atob(dataURI.substring(29));
const result = JSON.parse(json);
console.log(result);
Your use of Buffer in your question suggests to me that you may be using Node.js. If so, you'd replace the call to atob with Buffer.from(data, 'base64').toString():
const dataURI = "data:application/json;base64,ew0KICAgICJtYWx0X3R5cGUiOiAibG9nIiwNCiAgICAibWFsdF9kYXRhIjogIldvdywgdSByIGFsbW9zdCB0aGVyZSA6TyINCn0=";
// 29 = length of "data:application/json;base64,"
const json = Buffer.from(dataURI.substring(29), "base64").toString();
const result = JSON.parse(json);
console.log(result);

If you don't mind changing the context into an asynchronous one you could use fetch() to parse the recourse. fetch() is normally used with URLs, but works with data URIs as well (in most browsers).
const dataURI = "data:application/json;base64,ew0KICAgICJtYWx0X3R5cGUiOiAibG9nIiwNCiAgICAibWFsdF9kYXRhIjogIldvdywgdSByIGFsbW9zdCB0aGVyZSA6TyINCn0=";
(async function () {
const response = await fetch(dataURI);
const data = await response.json();
console.log(data);
})();
If you are already using a library to simplify network requests, you could use them as well.
Examples:
jQuery:
const dataURI = "data:application/json;base64,ew0KICAgICJtYWx0X3R5cGUiOiAibG9nIiwNCiAgICAibWFsdF9kYXRhIjogIldvdywgdSByIGFsbW9zdCB0aGVyZSA6TyINCn0=";
(async function() {
const data = await $.getJSON(dataURI);
console.log(data);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
axios:
const dataURI = "data:application/json;base64,ew0KICAgICJtYWx0X3R5cGUiOiAibG9nIiwNCiAgICAibWFsdF9kYXRhIjogIldvdywgdSByIGFsbW9zdCB0aGVyZSA6TyINCn0=";
(async function() {
const response = await axios.get(dataURI);
console.log(response.data);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.0/axios.min.js"></script>

Related

Fail to upload local CSV file with fetch() and fail to execute FileReader()

I'm trying to manipulate a local CSV file with JavaScript. My purpose is to display datas from my CSV on my website, like we were using an external API in JSON format for example.
const csvLocalFile =
"http://XXX/.../file.csv";
const openFile = async () => {
const csv = await fetch(csvLocalFile).then();
let reader = new FileReader();
reader.onload = function () {
let text = reader.result;
filecontent = text.replace("", "");
};
reader.readAsText(csv.files[0]);
};
openFile();
Chrome display this error :
TypeError: Cannot read properties of undefined (reading '0')
When I delete "[0]" from "reader.readAsText(csv.files[0])", I have this message error :
TypeError: Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'.
A empty .then() isn't the problem, turns out it works fine without a fn. but you should remove it regardless.
The FileReader can't read Response objects, only File & Blobs...
You say that you try to read a local file, but yet you use fetch to get a remote file, so what is it that your really trying to do? it's unclear of how to help you...
a csv isn't valid json data, so you can't use .then((res) => res.JSON())
beside res.JSON() is wrong, it should be all lowercased... res.json()
The FileReader is considered legacy so you no longer need it... use await blob.text() instead
here are two examples of how to read 1 remote file using fetch
// Simulate getting a file from eg a file input or drag and drop
const file = new File(['id,name\n10,bob'], 'file.csv', { type: 'text/csv' })
// Simulate a remote location to get the csv from
const url = URL.createObjectURL(file)
const csvLocalFile = url // http://XXX/.../file.csv
const openFile = async () => {
const response = await fetch(csvLocalFile)
const text = await response.text()
console.log(text)
}
openFile()
...and another with a actual local file selected from a user input
const fileInput = document.querySelector('#fileInput')
fileInput.onchange = async () => {
const file = fileInput.files[0]
const text = await file.text()
console.log(text)
}
// ignore code below this line...
// Create a dummy file that we can use to change the file input with...
const dummyFile = new File(['id,name\n10,bob'], 'file.csv', { type: 'text/csv' })
// Used for creating a new FileList in a round-about way
const b = new ClipboardEvent('').clipboardData || new DataTransfer()
b.items.add(dummyFile)
// simulate picking a file
fileInput.files = b.files
fileInput.onchange()
<input type="file" id="fileInput">

Problems with Parse json to retrieve the web page response

I have this web page response :
{"Status":"OK","RequestID":"xxxxxxxxxx","Results":[{"SubscriberKey":"teste132133","Client":null,"ListID":0,"CreatedDate":"0001-01-01T00:00:00.000","Status":"Active","PartnerKey":null,"PartnerProperties":null,"ModifiedDate":null,"ID":0,"ObjectID":null,"CustomerKey":null,"Owner":null,"CorrelationID":null,"ObjectState":null,"IsPlatformObject":false}],"HasMoreRows":false}
And I would like to just retrieve the SubscriberKey, like : "SubscriberKey":"teste132133"
So, I'm trying to use the Parse Json, but I believe that I'm doing something wrong that I don't know
follow the code :
<script language="javascript" runat="server">
Platform.Load("Core","1");
var response = HTP.Get("https://xxxxxxxx.pub.sfmc-content.com/vjpsefyn1jp"); //web page link
var obj = Platform.Function.ParseJSON(response);
Write(obj.Results[0].SubscriberKey)
</script>
I only know client side JavaScript, maybe this will work for you, it uses fetch to get the reponse, and then extracts the json value. It uses an asynchronous function call so we can use await to make the code more readible.
<script type="module">
async function getKey() {
const response = await fetch("https://xxxxxxxx.pub.sfmc-content.com/vjpsefyn1jp")
const json = await response.json()
const Results = json.Results
const key = Results[0].SubscriberKey
return key;
}
const key = await getKey();
console.log(`The key is: ${key}`);
</script>

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);
});

How to reconstruct the PNG returned by canvas.toBlob() in NodeJs

Let's say I have a canvas in an HTML file (nothing special). And I'm using Puppeteer to draw something on the canvas in the browser context and then pass it to NodeJs context where I save it as a PNG file using OpenCV.
Since binary data cannot be transferred between the two contexts (the browser and Node), I have to convert the binary data to a string and reconstruct the binary data in Node. The following code does exactly that:
const puppeteer = require('puppeteer');
const cv = require('opencv4nodejs');
const pup = puppeteer.launch({
headless: false,
args: [
'--use-gl=swiftshader',
'--no-sandbox',
'--enable-surface-synchronization',
'--disable-web-security',
]
}).then(async browser => {
const page = (await browser.pages())[0];
page.on('console', msg => console.log(msg.text()));
page.on("pageerror", function(err) {
const theTempValue = err.toString();
console.log("Page error: " + theTempValue);
});
page.on("error", function (err) {
const theTempValue = err.toString();
console.log("Error: " + theTempValue);
});
await page.exposeFunction('_setupCompleted', async () => {
await page.evaluate(async () => {
const c = document.getElementById("myCanvas");
const dataUrl = c.toDataURL("image/png");
const txt = await new Promise(resolve => c.toBlob((blb) => blb.text().then(resolve), "image/png"));
await window._saveMat(dataUrl, txt);
});
await browser.close();
});
await page.exposeFunction('_saveMat', async (dataUrl, txt) => {
dataUrl = dataUrl.replace(/^data:image\/png;base64,/, "");
const dataUrlBuffer = Buffer.from(dataUrl, 'base64');
const dataUrlMat = cv.imdecode(dataUrlBuffer, -1);
cv.imwrite(`./dataUrl.png`, dataUrlMat);
const txtBuffer = Buffer.from(txt, 'utf8');
const txtMat = cv.imdecode(txtBuffer, -1);
cv.imwrite(`./txtMat.png`, txtMat);
});
await page.goto('http://127.0.0.1:8887/index.html', {
waitUntil: 'networkidle2',
});
});
I the given code, I transfer the PNG in two ways. First, I use the toDataURL method of the canvas. This method encodes the binary data of the canvas using base64 and prepends some signature to it as well. Once received, the code in Node will strip the signature and decodes the base64. This part of the code works perfectly and it saves the PNG just fine.
The other approach uses the toBlob method of the canvas. This method returns a Blob which I'll call its text method to convert it to a string. On the Node side, I'll try to reconstruct a buffer out of the transferred string. This part is failing. Apparently, the reconstructed buffer is not a valid PNG and the imdecode method fails to create a mat object based on it.
My question is, how can I reconstruct the same buffer as I get from toDataURL using the text I get from the toBlob method in NodeJs?

NodeJS + ldapsj-client: problem saving thumbnailPhoto

Using the ldapsj-client module, I'm trying to save the thumbnailPhoto into a file
const auth = async () => {
const client = new LdapClient({ url: 'myaddomain' })
await client.bind('someemail#domain.com.br', 'passwaord')
const opts = {
filter: `(sAMAccountName=credential)`,
scope: "sub"
}
const s = await client.search(myBaseDN, opts)
console.log('thumbnailPhoto', s[0].thumbnailPhoto)
}
The console.log() outputs something like '����JFIF��C...'
I cannot figure out how to save this binary into a file. When I try several approaches, as explained here, does not work. It seems the data from AD is not in the same "format".
I tried to convert it into a Buffer and then, to base64
const buffer = Buffer.from(s[0].thumbnailPhoto, 'binary')
var src = "data:image/png;base64," + Buffer.from(s[0].thumbnailPhoto).toString('base64')
But the output is not a valid base64.

Categories

Resources