NodeJS converting image stream to base64 gives invalid data - javascript

I'm trying to generate a QR code and then return it as a Base64-encoded data URL. I know that there's a module (https://github.com/cmanzana/qrcode-npm) which is supposed to be able to do this directly, but I'm having trouble installing the canvas module dependency. I'm still working on that front but for now, my attempted workaround is to generate an image stream with an alternate module, then convert it to Base64. This is what I have so far:
var qrBase64 = '';
var qrImg = qr.image(qrText, { type: 'png', ec_level: 'L' });
qrImg.on('readable', function () {
qrBase64 += qrImg.read().toString('base64');
});
qrImg.on('end', function () {
qrBase64 = "data:image/png;base64," + qrBase64;
return res.json({
success: true,
qrBase64: qrBase64
});
});
It seems to work in that it gives me a string which resembles a Base64-encoded string. However, if I try to view it in a browser, I get an invalid URL error. If I pipe the qrImg to a file and then use an online tool to convert it to Base64, the result (which is valid and works in a browser) does not match my Node result.

You need to base64 encode all of the image data at once. Concatenating chunks before and after base64 encoding usually doesn't yield the same result. Take a look at this example:
btoa("12" + "34") -> "MTIzNA=="
btoa("12") + btoa("34") -> "MTI=MzQ="

Related

I am trying To save file in Windows-1255 Encoding

I am using fs.writefile and I can't save it in ANSI1255.
The file is UTF-8 encoded.
const encodedData = windows1255.encode(doc);
Don't work for me
Can't you just use the optional options.encoding param like this?
filehandle.writeFile(data, {
encoding: 'ANSI1255' // or whatever it's called properly
});
If that doesn't work, this might: https://stackoverflow.com/a/53855344/7451109

Converting base64 data from json response into ms excel file using javascript

I've seen SO questions similar to my use case w/ angular and other server side platforms but not for pure javascript.
I have an app where I do a $.ajax and do a get call to an API, which returns a previously converted excel file (excel to base64); I need to re-convert this base64 data back into it's original form - i.e. into Excel file. I tried retracing the steps I took to convert the excel into base64, reversing some of them, but I'm not able to generate the original file. An excel file IS being generated, but it still has base64 data and therefore opens w/ errors and in a corrupted state.
Has anyone else successfully done this?
Below is my code and fiddle link: (I didn't add the base64 json data (responseData) here since it's large, but it's on the fiddle)
var bindata = window.atob(responseData);
function DownloadExcel() {
window.location.href = "data:application/vnd.ms-excel;base64, bindata"
}
var blob = new Blob([responseData], {type: 'application/vnd.ms-excel'});
if (window.navigator && window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(blob);
}
else {
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}
jsfiddle link: https://jsfiddle.net/damon_matt/2ofz6xrd/

ASCII to Base64 in JavaScript

I'm trying to pull an image via GET /url.jpg and in the response is the image's ASCII representation. I then take that and try to Base64 encode it so I can display the image via html in an src tag. Here's the code I'm using:
api.getImg()
.then(function(res){
var reader = new window.FileReader();
var data = new Blob([res.data], {type: 'image/jpg'});
reader.readAsDataURL(data);
reader.onloadend = function() {
// sets the base64 encoded image to ng-src via AngularJS
vm.imgVis.viz1.link = reader.result;
}
});
The encoded image is then passed into the ng-src tag and nothing is loaded, broken image. I then take the base64 string to online base64 to image converters and nothing works there either.
Next, I tried directly uploading the image into an 'image to base64' converter and I get a completely new base64 string that works just fine anywhere I use it. Additionally, I turned this new string into an ASCII format and it looks nearly identical to the original GET response, however it appears the unprinted ASCII chars such as NULL are not being represented the same.
I think my issue might be with the ASCII character set. Could that be my problem? I feel like I'm missing a step.
Thanks
Edited to add API call:
function getImg() {
var settings = {
"url": "assets/apple.jpg",
"method": "GET",
"headers": {}
}
return $http(settings)
.then(function(response) {
return response;
})
.catch(function(e) {
return e;
});
}
And here is the actual image:
Apple

image onload not firing javascript when source is base64 websocket data

I have a Custom helpdesk application that I am trying to run in javascript.
the program has a peice of code that runs on the customer's computer and sends an image to a autobahn websocket server which acts as a proxy to a image viewer which can send clicks and keystrokes back over the websockets. this is all currently working in python correctly however, when i try it in javascript, I cannot get my image loaded no matter what I do and I can't figure out what i am doing wrong.
This is the part of my javascript that is broken:
function onMessage(evt) {
if(evt.data.indexOf('[00000]')>=0){
var ar = evt.data.split('[00000]');
if (ar[0] == "[IMAGE]"){
var imgdata = evt.data.split('[22222]');
context.width = imgdata[0];
context.height = imgdata[1];
console.log(context.width + " " + context.height)
try{
var img = new Image();
img.src = imgdata[2];
context.drawImage(img,0,0);
console.log("IMAGE");
}catch(e){
console.log(e)
}
}else if(ar[0] == "[RETCONN]"){
console.log("Accepted!");
}
}
}
Below is some code from the server to try and clarify what is going on with the javascript.
def onMessage(self, payload, isBinary):
if isBinary:
print("Binary message received: {0} bytes".format(len(payload)))
else:
msg = payload.decode('utf8')
com, data, arg = msg.split('[11111]')
if com == ("[IMAGE]"):
for name, conn in clients.items():
if name == data:
conn.sendMessage(('[IMAGE]'+'[00000]'+arg).encode('utf8'))
break
and this is how the image is put together from the customer side:
data = image.tostring()
data = base64.b64encode(data)
self.sendMessage(('[IMAGE]' + '[11111]' + rid + '[11111]' + str(w) + '[22222]' + str(h) + '[22222]' + data).encode('utf8'))
Anyone have any ideas how what i am doing wrong in my javascript?
EDIT: i am aware that img.src is in the wrong location. moving to the right spot does not fix the issue
If you want to use base64 encoded image as a source for the image object, it needs to be in format:
data:image/png;base64,<base64 encoded image>
You need to prepend data:image/png;base64, to your base64 string
img.src = "data:image/png;base64,"+imgdata[2];
You are also parsing your messages wrong.
imgdata[0] is supposed to be your width, but it also includes [IMAGE][00000].
You probably want ar[1].split('[22222]'); instead of evt.data.split('[22222]');.
To avoid complications with encoding, I would recommend you to use JSON to encode your WebSocket messages.
Edit:
You are getting a broken image because image.tostring() returns raw image data, but with data:image/png;base64, it's expected to be in PNG format.
To get base64 encoded PNG data use this:
import io
buffer = io.BytesIO()
image.save(buffer, "png")
data = base64.b64encode(buffer.getvalue())

Decode Base64 encoded PDF content in browser

We transform HTML to PDF in the backend (PHP) using dompdf. The generated output from dompdf is Base64 encoded with
$output = $dompdf->output();
base64_encode($output);
This Base64 encoded content is saved as a file on the server. When we decode this file content like this:
cat /tmp/55acbaa9600f4 | base64 -D > test.pdf
we get a proper PDF file.
But when we transfer the Base64 content to the client as a string value inside a JSON object (the server provides a RESTful API...):
{
"file_data": "...the base64 string..."
}
And decode it with atob() and then create a Blob object to download the file later on, the PDF is always "empty"/broken.
$scope.downloadFileData = function(doc) {
DocumentService.getFileData(doc).then(function(data) {
var decodedFileData = atob(data.file_data);
var file = new Blob([decodedFileData], { type: doc.file_type });
saveAs(file, doc.title + '.' + doc.extension);
});
};
When we log the decoded content, it seems that the content is "broken", because several symbols are not the same as when we decode the content on the server using base64 -D.
When we encode/decode the content of simple text/plain documents, it's working as expected. But all binary (or not ASCII formats) are not working.
We have searched the web for many hours, but didn't find a solution for this that works for us. Does anyone have the same problem and can provide us with a working solution? Thanks in advance!
This is a example for a on the server Base64 encoded content of a PDF document:
JVBERi0xLjMKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZwovT3V0bGluZXMgMiAwIFIKL1BhZ2VzIDMgMCBSID4+CmVuZG9iagoyIDAgb2JqCjw8IC9UeXBlIC9PdXRsaW5lcyAvQ291bnQgMCA+PgplbmRvYmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZXMKL0tpZHMgWzYgMCBSCl0KL0NvdW50IDEKL1Jlc291cmNlcyA8PAovUHJvY1NldCA0IDAgUgovRm9udCA8PCAKL0YxIDggMCBSCj4+Cj4+Ci9NZWRpYUJveCBbMC4wMDAgMC4wMDAgNjEyLjAwMCA3OTIuMDAwXQogPj4KZW5kb2JqCjQgMCBvYmoKWy9QREYgL1RleHQgXQplbmRvYmoKNSAwIG9iago8PAovQ3JlYXRvciAoRE9NUERGKQovQ3JlYXRpb25EYXRlIChEOjIwMTUwNzIwMTMzMzIzKzAyJzAwJykKL01vZERhdGUgKEQ6MjAxNTA3MjAxMzMzMjMrMDInMDAnKQo+PgplbmRvYmoKNiAwIG9iago8PCAvVHlwZSAvUGFnZQovUGFyZW50IDMgMCBSCi9Db250ZW50cyA3IDAgUgo+PgplbmRvYmoKNyAwIG9iago8PCAvRmlsdGVyIC9GbGF0ZURlY29kZQovTGVuZ3RoIDY2ID4+CnN0cmVhbQp4nOMy0DMwMFBAJovSuZxCFIxN9AwMzRTMDS31DCxNFUJSFPTdDBWMgKIKIWkKCtEaIanFJZqxCiFeCq4hAO4PD0MKZW5kc3RyZWFtCmVuZG9iago4IDAgb2JqCjw8IC9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQovTmFtZSAvRjEKL0Jhc2VGb250IC9UaW1lcy1Cb2xkCi9FbmNvZGluZyAvV2luQW5zaUVuY29kaW5nCj4+CmVuZG9iagp4cmVmCjAgOQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDggMDAwMDAgbiAKMDAwMDAwMDA3MyAwMDAwMCBuIAowMDAwMDAwMTE5IDAwMDAwIG4gCjAwMDAwMDAyNzMgMDAwMDAgbiAKMDAwMDAwMDMwMiAwMDAwMCBuIAowMDAwMDAwNDE2IDAwMDAwIG4gCjAwMDAwMDA0NzkgMDAwMDAgbiAKMDAwMDAwMDYxNiAwMDAwMCBuIAp0cmFpbGVyCjw8Ci9TaXplIDkKL1Jvb3QgMSAwIFIKL0luZm8gNSAwIFIKPj4Kc3RhcnR4cmVmCjcyNQolJUVPRgo=
If you atob() this, you don't get the same result as on the console with base64 -D. Why?
Your issue looks identical to the one I needed to solve recently.
Here is what worked for me:
const binaryImg = atob(base64String);
const length = binaryImg.length;
const arrayBuffer = new ArrayBuffer(length);
const uintArray = new Uint8Array(arrayBuffer);
for (let i = 0; i < length; i++) {
uintArray[i] = binaryImg.charCodeAt(i);
}
const fileBlob = new Blob([uintArray], { type: 'application/pdf' });
saveAs(fileBlob, 'filename.pdf');
It seems that only doing a base64 decode is not enough...you need to put the result into a Uint8Array. Otherwise, the pdf pages appear blank.
I found this solution here:
https://github.com/sayanee/angularjs-pdf/issues/110#issuecomment-579988190
You can use btoa() and atob() work in some browsers:
For Exa.
var enc = btoa("this is some text");
alert(enc);
alert(atob(enc));
To JSON and base64 are completely independent.
Here's a JSON stringifier/parser (and direct GitHub link).
Here's a base64 Q&A. Here's another one.

Categories

Resources