Base64 in Javascript - javascript

I send some image from java.
I need to do URLEncoder because I need to send the Base64 data in the URL
String base64Document = Base64.encode(documentBytes);
base64Document = URLEncoder.encode(base64Document, "UTF-8"); // This class contains static methods for converting a String to the application/x-www-form-urlencoded MIMEformat
But when I load this data I dont have any image.
I need a way to decode this.
My code works for canvas but not for image
console.log("Encoded" + vm.documentData.base64Document);
vm.documentData.base64Document = urlDecode(vm.documentData.base64Document);
console.log("Decoded" + vm.documentData.base64Document);
// Decode Safe URL Base64
function urlDecode(encoded) {
encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');
while (encoded.length % 4)
encoded += '=';
return new ArrayBuffer(encoded || '', 'base64').toString('utf8');
};
html
<img class="document" src="data:image/png;base64,{{vm.documentData.base64Document}}" />
GET data:image/png;base64,[object ArrayBuffer] net::ERR_INVALID_URL

ArrayBuffer.prototype.toString will always return [object ArrayBuffer].
If you need to convert it into a string, I suggest to read this answer: Converting between strings and ArrayBuffers

Related

I want to decompress a GZIP string with JavaScript

I have this GZIPed string: H4sIAAAAAAAA//NIzcnJVyguSUzOzi9LLUrLyS/XUSjJSMzLLlZIyy9SSMwpT6wsVshIzSnIzEtXBACs78K6LwAAAA==
I created that with this website: http://www.txtwizard.net/compression
I have tried using pako to ungzip it.
import { ungzip } from 'pako';
const textEncoder = new TextEncoder();
const gzipedData = textEncoder.encode("H4sIAAAAAAAA//NIzcnJVyguSUzOzi9LLUrLyS/XUSjJSMzLLlZIyy9SSMwpT6wsVshIzSnIzEtXBACs78K6LwAAAA==");
console.log('gzipeddata', gzipedData);
const ungzipedData = ungzip(gzipedData);
console.log('ungziped data', ungzipedData);
The issue is that Pako throws the error: incorrect header check
What am I missing here?
A JSbin
The "H4sIAAAAAAAA//NIzcnJVyguSUzOzi9LLUrLyS/XUSjJSMzLLlZIyy9SSMwpT6wsVshIzSnIzEtXBACs78K6LwAAAA==" is a base64 encoded string, you first need to decode that into a buffer.
textEncoder.encode just encodes that base64 encoded string into a byte stream.
How to do that depend on whether you are in a browser or on nodejs.
node.js version
To convert the unzipped data to a string you further have use new TextDecoder().decode()
For node you will use Buffer.from(string, 'base64') to decode the base64 encoded string:
import { ungzip } from 'pako';
// decode the base64 encoded data
const gzipedData = Buffer.from("H4sIAAAAAAAA//NIzcnJVyguSUzOzi9LLUrLyS/XUSjJSMzLLlZIyy9SSMwpT6wsVshIzSnIzEtXBACs78K6LwAAAA==", "base64");
console.log('gzipeddata', gzipedData);
const ungzipedData = ungzip(gzipedData);
console.log('ungziped data', new TextDecoder().decode(ungzipedData));
browser version
In the browser, you have to use atob, and you need to convert the decoded data to an Uint8Array using e.g. Uint8Array.from.
The conversion I used was taken from Convert base64 string to ArrayBuffer, you might need to verify if that really works in all cases.
// decode the base64 encoded data
const gezipedData = atob("H4sIAAAAAAAA//NIzcnJVyguSUzOzi9LLUrLyS/XUSjJSMzLLlZIyy9SSMwpT6wsVshIzSnIzEtXBACs78K6LwAAAA==")
const gzipedDataArray = Uint8Array.from(gezipedData, c => c.charCodeAt(0))
console.log('gzipeddata', gzipedDataArray);
const ungzipedData = pako.ungzip(gzipedDataArray);
console.log('ungziped data', new TextDecoder().decode(ungzipedData));
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.0.4/pako.min.js"></script>
This string is base64-encoded.
You first need to decode it to a buffer:
const gzippedString = 'H4sIAAAAAAAA//NIzcnJVyguSUzOzi9LLUrLyS/XUSjJSMzLLlZIyy9SSMwpT6wsVshIzSnIzEtXBACs78K6LwAAAA==';
const gzippedBuffer = new Buffer(gzippedString, 'base64');
Then you can un(g)zip it:
const unzippedBuffer = ungzip(gzippedBuffer);
The result on ungzip is a Unit8Array. If you want to convert it back to a string you'll need to decode it again:
const unzippedString = new TextDecoder('utf8').decode(unzipped);

Add = or == to a base64 if necessary

I am using the Ionic Choose plugin to take a file in an app, this one in the resolve returns me a base64 of the file I chose, the problem is that this base64 never ends with = or == when necessary in some cases.
When trying to send this base64 to the server it returns an error because the = or == is missing at the end of the string.
So I get the base64
this.chooser.getFile()
.then((file) => {
let base64 = file.dataURI;
})
.catch((err) => {
console.log(err);
});
Can I somehow detect if base64 needs either = or == to complete the string?
Base64 'blocks' consists of 4 characters, so if the final block contains less than 4 characters it gets padded with "=" sign, so it can have anywhere from 0 to 2 "=" signs in them, that's why the length of the dataURI needs to be a multiple of 4, You can do something like this:
let base64 = file.dataURI;
const len = base64.length;
const modifiedBase64 = base64 + "=".repeat(len%4);

JAVASCRIPT decode a base64string (which is an encoded zipfile) to a zipfile and get the zipfiles content by name

the question says it all, im receiving a base64 encoded ZIPFILE from the server, which I first want to decode to a ZIPFILE in memory and then get the ZIPFILES content, which is a json-file.
I tried to use JSZIP but im totally lost in this case ... the base64 string is received with javascript by a promise.
So my question in short is: How can I convert a base64 encoded ZIPFILE to a ZIPFILE in memory to get its contents.
BASE64 -> ZIPFILE -> CONTENT
I use this complicated process to save much space on my database. And I dont want to handle this process on server-side, but on clientside with JS.
Thanks in advance!
If anyone is interested in my solution to this problem read my answer right here:
I received the data in a base64-string format, then converted the string to a blob. Then I used the blob-handle to load the zipfile with the JSZip-Library. After that I could just grab the contents of the zipfile. Code is below:
function base64ToBlob(base64) {
let binaryString = window.atob(base64);
let binaryLen = binaryString.length;
let ab = new ArrayBuffer(binaryLen);
let ia = new Uint8Array(ab);
for (let i = 0; i < binaryLen; i++) {
ia[i] = binaryString.charCodeAt(i);
}
let bb = new Blob([ab]);
bb.lastModifiedDate = new Date();
bb.name = "archive.zip";
bb.type = "zip";
return bb;
}
To get the contents of the zipfile:
let blob = base64ToBlob(resolved);
let zip = new JSZip();
zip.loadAsync(blob).then(function(zip) {
zip.file("archived.json").async("string").then(function (content) {
console.log(content);
// content is the file as a string
});
}).catch((e) => {
});
As you can see, first the blob is created from the base64-string. Then the handle is given over to the JSZip loadAsync method. After that you have to set the name of the file which you want to retrieve from the zipfile. In this case it is the file called "archived.json". Now because of the async("string") function the file (file contents) are returned as a string. To further use the extracted string, just work with the content variable.

Node Buffer.prototype.toString returns incomplete string

Trying to parse a csv in node using a Buffer but the return value seems to be incomplete:
Code:
app.post('/upload/import', function(req, res) {
var base64str = req.body // which returns data:text/csv;base64,VGhpcyBpcyBhIHRoaW5nDTQxMDIxMjE4NzINOTA5ODc2MTI0NQ0yOTIxMjc
var data = base64str.substring(base64str.indexOf(',') + 1, base64str.length); \\ remove 'data:text/csv;base64,
var encoded = new Buffer(data, 'base64').toString('ascii');
console.log(encoded); // returns '2910387473thing'
});
When I run this exact base64 string through a base64 service I get this result:
This is a thing
4102121872
9098761245
2921278901
9981223489
6482034847
3948820123
8483920383
3849201837
2910387473
The base64 string is VGhpcyBpcyBhIHRoaW5nDTQxMDIxMjE4NzINOTA5ODc2MTI0NQ0yOTIxMjc4OTAxDTk5ODEyMjM0ODkNNjQ4MjAzNDg0Nw0zOTQ4ODIwMTIzDTg0ODM5MjAzODMNMzg0OTIwMTgzNw0yOTEwMzg3NDcz
This is the site where I've verified my base64 is correct: https://www.base64decode.org/
What is happening to truncate my data?

How to convert Byte[] formated image to Base64string using JavaScript

I want to display an image from sql db to my web page,
I got the image in the format
{byte[6317]}
How to convert it into Base64string.
Try this
Byte[] bytes = File.ReadAllBytes("path");
String file = Convert.ToBase64String(bytes);
And correspondingly, read back to file:
Byte[] bytes = Convert.FromBase64String(b64Str);
File.WriteAllBytes(path, bytes);
Javascript Approach with Base64.js library
Since u specified that u want to convert it using JavaScript you can do it with the Base64 JavaScript library. It has the following methods:
toByteArray - Takes a base64 string and returns a byte array
And
fromByteArray - Takes a byte array and returns a base64 string
Here is an example how you could do it. First, return from ASP.NET MVC a response like this:
return Json(new { Img = imageBytes }, JsonRequestBehavior.AllowGet);
And then on the client you can use jQuery getJson() function to get the JSON response from the MVC ImageController:
$.getJSON("/Image",function(result){
$.each(result, function(i, field){
var byteArray = result.Img;
var base64 = base64js.fromByteArray(byteArray);
$("#mainimg").attr('src', 'data:image/jpeg;base64,' + base64);
});
});
You can download the base64.js library from here:
https://github.com/beatgammit/base64-js
C# Convert approach
If you don't like the base64 javascript approach you could convert the byte array on the server with C# using:
String base64string = Convert.ToBase64String(imageBytes);
return Json(new { Img = base64string }, JsonRequestBehavior.AllowGet);
This would return the Base64 string in the JSON Result. Then you can easily set your img source from jQuery as displayed in the Javascript Approach example.
Try This Code,
byte[] imgBytes = (byte[])yourbytedata;
string base64String = Convert.ToBase64String(imgBytes, 0, imgBytes.Length);
string htmlstr = "data:image/png;base64," + base64String;

Categories