Basically what the title says; I have a base64 string that encodes an image and I want to convert it into a blob so I can pass it into my File constructor. I realise many similar questions have been asked however many of the other answers make use of the atob function which has been deprecated; So im trying to look for alternatives.
Try this
var base64String = "dGVzdAo=";
var blob = new Blob([base64String], {type: 'text/plain'});
Related
I'm using the following method to convert files into base64 encoding and it's been working fine for a long time, but I see now that Buffer is depricated.
// function to encode file data to base64 encoded string
function base64_encode(file) {
var bitmap = fs.readFileSync(file);
// convert binary data to base64 encoded string
return new Buffer(bitmap).toString("base64");
}
let base64String = base64_encode("Document.png");
Can someone please help me modify this to work with the new suggested method as I'm not sure how to modify it myself?
Thank you so much in advance.
It is not Buffer that is deprecated but its constructor, so instead of new Buffer() you use e.g. Buffer.from.
However fs.readFileSync already returns a Buffer if no encoding is specified, so there is not really a need to pass that to another buffer. Instead you can do return fs.readFileSync(file).toString("base64")
Using the Sync part of the API is most of the time something would like to avoid and if possible switch over to the promise-based API.
I retrieve an encoded string (using TextEncoder into UTF-8, which was stringified before sending to the server) from the server using AJAX. I parse it upon retrieval and get an Object. I need to convert this Object to a decoded string. TextDecoder seems to have decode method, but it expects ArrayBuffer or ArrayBufferView, not Object. That method gives TypeError if I use my Object as-is:
var myStr = "This is a string, possibly with utf-8 or utf-16 chars.";
console.log("Original: " + myStr);
var encoded = new TextEncoder("UTF-16").encode(myStr);
console.log("Encoded: " + encoded);
var encStr = JSON.stringify(encoded);
console.log("Stringfied: " + encStr);
//---------- Send it to the server; store in db; retrieve it later ---------
var parsedObj = JSON.parse(encStr); // Returns an "Object"
console.log("Parsed: " + parsedObj);
// The following decode method expects ArrayBuffer or ArrayBufferView only
var decStr = new TextDecoder("UTF-16").decode(parsedObj); // TypeError
// Do something with the decoded string
This SO 6965107 has extensive discussion on converting strings/ArrayBuffers but none of those answers work for my situation. I also came across this article, which does not work if I have Object.
Some posts suggest to use "responseType: arraybuffer" which results in ArrayBuffer response from the server, but I cannot use it when retrieving this encoded string because there are many other items in the same result data which need different content-type.
I am kind of stuck and unable to find a solution after searching for a day on google and SO. I am open to any solution that lets me save "strings containing international characters" to the server and "retrieve them exactly as they were", except changing the content-type because these strings are bundled within JSON objects that carry audio, video, and files. Any help or suggestions are highly appreciated.
Why is readAsBinaryString() deprecated? From W3C
The use of readAsArrayBuffer() is preferred over readAsBinaryString(), which is provided for backwards compatibility.
readAsBinaryString returns a completely different thing than the other method, so how could one be the replacement for the other?
In my specific case I have a Blob that I need to convert to base64, there are many ways, but most of them not memory efficient. As of my tests calling window.btoa() from readAsBinaryString' result works best. If I cannot use this anymore (or for now lets say "should"), then I must convert the array to a string using iteration and strings concatenation which is not memory efficient at all!
So after researching for days I don't really find an alternative to readAsBinaryString, that's why the question, or do you see an alternative that also works with 100MB blobs?
The history is that readAsBinaryString was present in an early specification of the FileReader API, before the ArrayBuffer interface exist.
When the ArrayBuffer interface appeared, readAsBinaryString has been deprecated because all its use cases could be done in a better way using that new interface.
Indeed, readAsBinaryString only converts the binary data into a DOMString (UTF-16). There is not much you can do from it afterward. Also, storing it as an UTF-16 string implies that it takes far more space in memory than the original data size. Add to this that strings are immutable, I guess you can see how inefficient it is to work from this.
And finally, if you really need to have this string, you can actually do the same from an ArrayBuffer, you just need to call String.fromCharCode over an Uint8 view of this ArrayBuffer.
// generate some binary data
document.createElement('canvas').toBlob(blob => {
const bin_reader = new FileReader();
const arr_reader = new FileReader();
let done = 0;
bin_reader.onload = arr_reader.onload = e => {
if(++done===2) {
const arr_as_bin = [...new Uint8Array(arr_reader.result)]
.map(v => String.fromCharCode(v)).join('');
console.log('same results: ', arr_as_bin === bin_reader.result);
console.log(arr_as_bin);
}
}
bin_reader.readAsBinaryString(blob);
arr_reader.readAsArrayBuffer(blob);
});
Now, this method, while still very useless, has been re-added to the specs, because some websites did start using it.
And to help OP a bit more, since what they were trying to do was actually to get a base64 version of their Blob, then don't even use readAsArrayBuffer(), readAsDataURL() is what you need:
const blob = new Blob(['hello']);
const reader = new FileReader();
reader.onload = e => {
const dataURL = reader.result;
const base64 = dataURL.slice(dataURL.indexOf(',')+1);
console.log(base64);
};
reader.readAsDataURL(blob);
As you know & stated in w3 it is possible to create a url for a Blob object in javascript by using Blob's createObjectUrl. On the other hand, if we have a data as a Base64 encoded string we can present it as a Url with the format "data[MIMEType];base64,[data>]".
Let's suppose that I have a base64 encoded string that was generated from an image that is very popular on these days :) "The red dot" image in wikipedia.
var reddotB64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg";
I'm 100% sure that if I create a URL conforming the Data URI Scheme as stated above, then, I'll be able to put a link element and download it from the browser: please see the code example below:
var reddotB64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg";
var reddotLink = document.createElement("a");
reddotLink.target = "_blank";
reddotLink.href = "data:image/png;base64," + reddotB64;
document.body.appendChild(reddotLink);
reddotLink.click();
document.body.removeChild(reddotLink);
This works prettywell and displays the image in a new tab. On the other hand I'll try to create the link by using Blob as follow:
var reddotB64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg";
var reddotBlob = new Blob([atob(reddotB64)], { type: 'image/png' });
var reddotLink = document.createElement("a");
reddotLink.target = "_blank";
reddotLink.href = URL.createObjectURL(reddotBlob);
document.body.appendChild(reddotLink);
reddotLink.click();
document.body.removeChild(reddotLink);
This code is decoding base64 encoded string variable reddotB64 via atob function. And then, creating a Blob object and continues with URL.createObjectURL function. In that case, since I've decoded reddotB64 from base64 to binary and created a Blob of type image/png and then create object url from that I expect it to work but it's not working.
Do you have a clue why it's not working? Or am I missing anything on the standards? Or doing something wrong in Javascript?
Here is the answer. Looks like it is an encoding issue. In order to convert/decode Base64 string to binary(UInt8Array/byte) using atob is not enough. After using atob it is required to use UTF-16 character code: and we achieve this by using charCodeAt function for every character in the decoded string. As a result we get UTF-16 encoded binary string which is definately working. Just create a Blob and then call URL.createObjectURL.
I am trying to convert a base64 string to byte array and open it as a pdf file in IE. The only problem is atob is not supported in IE, so trying to use Buffer like this:
let b64Data = myBase64Url.split(',', 2)[1];
var byteArray = new Buffer(b64Data ,'base64').toString('binary');
var blob = new Blob([byteArray], {type: 'application/pdf'});
window.navigator.msSaveOrOpenBlob(blob);
I am getting a popup successfully to open the file
But the file is corrupted
What am i doing wrong ? Is there a better way to convert base64 to byte array in IE ?
In order for the base64 to be properly decoded, it must be only the base64 data, i.e. no mimetype information preceding it.
You will also need to remove .toString('binary') so that you're passing a buffer instead of a string.