I want to download some binary data but Chrome forces it to utf-8 which messes up the bytes. If I set href to a data URI and use base64 encoding it works, but I want to avoid that and use a BLOB instead.
Is there a way to stop Chrome from converting this binary data to utf-8?
const data = "\x00\xff\xfe\xe2"
console.log(data)
const file = new Blob([data])
const a = document.getElementById("a")
const url = URL.createObjectURL(file)
a.href = url;
a.download = "test.txt";
<a id="a">Download</a>
In this example, you can see that my string contains the bytes
00 ff fe e2
and I convert that string to a blob. But when you download the file in Chrome and look at the bytes again you'll find
20 c3 bf c3 be c3 a2
instead.
What I think is happening is that chrome takes each byte, reads it as utf-16 and converts it to utf-8. For example fe is þ when read as utf-16 but c3 be in utf-8
Strings are implicitly encoded as UTF-8 by the Blob constructor, so pass a typed array instead, such as Uint8Array:
const data = "\x00\xff\xfe\xe2"
console.log(data)
const file = new Blob([Uint8Array.from(data, c => c.charCodeAt(0))])
const a = document.getElementById("a")
const url = URL.createObjectURL(file)
a.href = url;
a.download = "test.txt";
<a id="a">Download</a>
Related
I am simply trying to convert a base-64 string to csv. The file is in CSV format transmitted in base-64 string.
I am implementing this in Microsoft Office Excel Addins
Code base-64-string
// getting the base-64 string
let base_64_string = [base-64-string];
// decode the base-64 string
let csvContent = atob(base_64_string);
// convert the decoded base-64 string to csv
var blob = new Blob([csvContent], {type: "data:application/octet-stream;base64"});
Error
Compiled with problems:
WARNING in ./src/taskpane/taskpane.js 310:17-21
export 'Blob' (imported as 'Blob') was not found in 'buffer' (possible exports: Buffer, INSPECT_MAX_BYTES, SlowBuffer, kMaxLength)
Another method here
The code you've posted is not the problem (as demonstrated by the code snippet below).
// generate a base-64 encoded csv string
const base_64_string = btoa("a,b,c");
// decode the base-64 string
const csvContent = atob(base_64_string);
// convert the decoded base-64 string to csv
const blob = new Blob([csvContent], {type: "data:application/octet-stream;base64"});
console.log(blob);
I have a string, On which I need to encode it into "iso-8859-1" and then I need to convert back it into a readable string.
Is there any way to do this in node js natively? If I am encoding it into "iso-8859-1" then do I need to use the same to decode it back?
I am able to do it in .Net
string encodedData = "VABpAG0AZQAgAHMAZQByAGUAaQBzAA==";
Encoding encoding = Encoding.GetEncoding("iso-8859-1"); // encoding in "iso-8859-1"
byte[] = decodedbuff = convert.FromBase64String(encodedData); // getting buffer
result = encoding.GetString(decodedbuff); //decoding
How to achieve it in node js?
You can simply create a buffer from your encoded base64 string and then use toString() with latin1 (iso-8859-1 is latin1 in nodejs) on the buffer to get the decoded string:
const encoded = "VABpAG0AZQAgAHMAZQByAGUAaQBzAA==";
const buffer = Buffer.from(encoded, 'base64');
console.log(buffer.toString('latin1')); // prints T i m e s e r e i s
This question already has answers here:
Creating a BLOB from a Base64 string in JavaScript
(15 answers)
Closed 5 years ago.
I am trying to download xlsx spreadsheet with javascript. I have tested base64 data. I decode it like so:
var data = atob(validBase64Data);
After that, I do:
save(name, data, type) {
const blob = new Blob([data], {type: type});
let objectURL = window.URL.createObjectURL(blob);
let anchor = document.createElement('a');
anchor.href = objectURL;
anchor.download = name;
anchor.click();
URL.revokeObjectURL(objectURL);
}
Where name is a filename.xlsx, data is the decoded data and type is a mime-type string.
The excel file is downloaded but would not open as excel. Data is corrupted somehow.
In addition: I tested the same data with a unix terminal command to base64 decode and write the xlsx directly into that file, and that produced working file. Test was done like so:
I saved base64 data to test_excel.txt`
Ran command base64 -D -i test_excel.txt -o test_excel.xlsx
test_excel.xlsx is recognized by excel.
What am I doing wrong with the code?
Here is the code that solved it:
export default {
save(name, data, type, isBinary) {
if (isBinary) {
var bytes = new Array(data.length);
for (var i = 0; i < data.length; i++) {
bytes[i] = data.charCodeAt(i);
}
data = new Uint8Array(bytes);
}
var blob = new Blob([data], {type: type});
let objectURL = window.URL.createObjectURL(blob);
let anchor = document.createElement('a');
anchor.href = objectURL;
anchor.download = name;
anchor.click();
URL.revokeObjectURL(objectURL);
}
}
Thanks to everyone who participated in resolving.
Also, credits to: Creating a Blob from a base64 string in JavaScript
Okay, so let's clarify a few things before anyone tries to "explain" the problem incorrectly.
The original .xlsx is a binary-encoded file, meaning that the data will contain bytes in the full range of 0x00 to 0xFF.
In the question, it is assumed that this string has been successfully encoded into a valid base64 string, with no extraneous characters (as indicated by the success of the test using base64 without the -i flag), and stored to validBase64Data.
The problem is that atob(validBase64Data) generates a string decoded into utf-8, not binary. And as I said before, the original binary string contains non-ASCII bytes in the range 0x80 to 0xFF. In utf-8, these code points are stored as two bytes instead of one, so the solution, as described in Creating a Blob from a base64 string in JavaScript, is to convert the code points of each character in the utf-8 string data into bytes stored as a Uint8Array, and then construct a Blob from that.
A naive solution might look like this, though please refer to Creating a Blob from a base64 string in JavaScript for more performant solutions:
const blob = new Blob([Uint8Array.from(data, c => c.charCodeAt(0))], { type });
//...
This uses TypedArray.from(iterable, mapFn).
I am trying to convert pdf and image files to base 64 using javascript and convert it back to file using C# in WEB API.
Javascript
var filesSelected = document.getElementById("inputFileToLoad").files;
if (filesSelected.length > 0)
{
var fileToLoad = filesSelected[0];
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent)
{
var textAreaFileContents = document.getElementById("textAreaFileContents");
textAreaFileContents.innerHTML = fileLoadedEvent.target.result;
};
fileReader.readAsDataURL(fileToLoad);
}
C#
Byte[] bytes = Convert.FromBase64String(dd[0].Image_base64Url);
File.WriteAllBytes(actualSavePath,bytes);
But in API I'm getting exception as {"The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters. "}
Please tell me how to proceed with this...
Thanks
According to MDN: FileReader.readAsDataURL those generated URLs are prefixed with something like data:image/jpeg;base64,. Have a look at your generated string. Look for the occurence of base64, and take the base64 data that starts after this prefix.
Because the FileReader.readAsDataURL() produces a string that is prefixed with extra metadata (the "URL" portion), you need to strip it off on the C# side. Here's some sample code:
// Sample string from FileReader.readAsDataURL()
var base64 = "data:image/jpeg;base64,ba9867b6a86ba86b6a6ab6abaa====";
// Some known piece of information that will be in the above string
const string identifier = ";base64,";
// Find where it exists in the input string
var dataIndex = base64.IndexOf(identifier);
// Take the portion after this identifier; that's the real base-64 portion
var cleaned = base64.Substring(dataIndex + identifier.Length);
// Get the bytes
var bytes = Convert.FromBase64String(cleaned);
You could condense this down if it's too verbose, I just wanted to explain it step by step.
var bytes = Convert.FromBase64String(base64.Substring(base64.IndexOf(";base64,") + 8));
I try to encode a string in both browser and server but I have different base64 encoding for a specific string
Here is my string: "£aº©S=³hPó c¨¸" (Hexa: 00a3006100ba00a900940053003d00b30068005000f300900020006300a800b8 )
Client-side: I encode this String using btoa() and I have : o2G6qZRTPbNoUPOQIGOouA== and this is the result I expect.
Server-side: I code this String using Buffer according to this answer in Node.js i have :
var ciphertext = ... // myString
console.log(ciphertext.hexEncode()); // 00a3006100ba00a900940053003d00b30068005000f300900020006300a800b8
console.log(Buffer.from(ciphertext, 'utf8').toString('base64')) // wqNhwrrCqcKUUz3Cs2hQw7PCkCBjwqjCuA==
console.log(Buffer.from(ciphertext, 'ucs2').toString('base64')) // owBhALoAqQCUAFMAPQCzAGgAUADzAJAAIABjAKgAuAA=
I managed to obtain the base64 encoding I expect using the node-package base-64
I still don't know why, so if someone has a clue
var base64 = require('base-64');
var ciphertext = ...; //myString
var encoded = base64.encode(bytes);
console.log(encoded); // o2G6qZRTPbNoUPOQIGOouA==