Base64 encode/decode and download content generated in URL - javascript

I am generating a string through JavaScript and I need to download it to a text file with a predefined dynamic filename. This way there will be no room for error by employees.
This is obviously not possible in JavaScript due to security issues. However, from what I have read it should be possible with base64 encoding.
I managed to encode the string and open a url with the decoded data. The string has been decoded successfully in this URL. The format is as follows:
var data = 'data:text/plain;base64,'+L_EncodedData;
document.location = data;
I need to open a file dialog with the decoded data so the employees can download the content generated in this URL.
Any help?
Many thanks in advance

If you're still looking for an answer to this, check out my answer here. This is how I would adapt it for your needs.
// Convert the Base64 string back to text.
var txt = atob(data.reportBase64Bytes);
// Blob for saving.
var blob = new Blob([byteString], { type: "text/plain" });
// Tell the browser to save as report.txt.
saveAs(blob, "report.txt");
If you use this, make sure you grab the polyfills that I mention in the other post.

This block is fixed.
window.OpenWindowForBase64 = function(url, callback) {
var image = new Image();
image.src = url;
var w = window.open("");
w.document.write(image.outerHTML);
if (callback) {
callback(url);
}
}

Related

URL.createObjectURL and charset UTF-8

i have problem with encoding my text
var description = "jak używać?"
var blob = new Blob([description], {
type: "text/plain;charset=utf-8;"
});
var url = URL.createObjectURL(blob);
console.log(url)
where i enter to url my description isnt same and return jak uĹźywaÄ? What i doing wrong?
Add Byte order mark to the array header.
blob = new Blob(["\ufeff", description]);
https://stackoverflow.com/a/18925211/9867895
https://en.wikipedia.org/wiki/Byte_order_mark
Try:
...
var blob = new Blob([**"\ufeff",** description], {
...
URL.creatObjectUrl doesn't seem to work with raw UTF-8 strings. The solution provided for binary data https://stackoverflow.com/a/36955941/70716 should work. the answers to Creating a Blob from a base64 string in JavaScript also include some additional explanation of the issue and alternative code examples.

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.

Oracle Apex Canvas to blob in PNG format saved to item

I am struggling to convert my canvas URL to a blob format, specifically in PNG format. The DataURL is generating quite perfectly when I tested it without the conversion code, the problem comes in when trying to convert it to Blob. I am using an html button that triggers the JavaScript function with the ID buttonTextArea.
I need the Blob file to be linked to my APEX page item, which I use the $s('P9_IMAGE_CODE', Blob) format, which also works when I tested it using text only. Once the page is processed, that item will be sent into a blob column within my table.
Here is my code:
$("#buttonTextArea").click(function(dataURL) {
var BASE64_MARKER = ';base64,';
var canvas = document.getElementById('myCanvas');
var dataURL = canvas.toDataURL();
if (dataURL.indexOf(BASE64_MARKER) == -1) {
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[1];
var raw = decodeURIComponent(parts[1]);
return new Blob([raw], {type: contentType});
}
var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], {type: contentType});
document.getElementById("textArea").value = dataUrl;
$s('P9_IMAGE_CODE', Blob); --P9_IMAGE_CODE IS THE ITEM ON MY PAGE
});
I have been trying examples from :
https://github.com/blueimp/JavaScript-Canvas-to-Blob/blob/master/README.md
and
https://code.google.com/p/chromium/issues/detail?id=67587
Thank you in advance.
As Jeffrey pointed out, the javasscript "Blob" is not the same as the Oracle BLOB datatype.
The toDataURL function is already returning a base64 encoded string, so what you'd need to do is to save that string and then after submit convert it into a real blob.
Sending it to the database may be a bit of an issue since there is a limit of 32k bytes on an item's content. This means you'll likely have to send the string in chunks to the database. This is then not a VARCHAR2 (which also has a limit of 32k) but a CLOB.
As Wesley points out, there are some workarounds for that. The blog he linked to is one such example. There is also a plugin to facilitate the handling of clobs in apex.
Once you get the base64 string to the database, you'll have to convert it to a real blob. There is no built-in to quickly do this, but once again this is something several people have already solved.
A script is provided here by Tim Hall to convert a CLOB to a BLOB.
So:
In the browser, get the dataURL, which is a base64 encoded string
send it in chunks to the database, where it'll be a CLOB
after everything has been sent, convert the CLOB to a BLOB and save
it in your table

How to create a Blob object from image url?

I am using Winjs(javascript for windows 8 app).
what I want is to create a simple blob object from a specific url of my static image by giving the path.
What is the solution?
Any help will be appreciated.
'MSApp.CreateFileFromStorageFile()` as used below will work. if you need to send the file using WinJS.xhr() you can set as data in xhrOptions.
var uri = new Windows.Foundation.Uri('ms-appx:///images/IMG_0550.jpg');
var self = this;
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function ongetfilecomplete(storageFile)
{
var file = MSApp.createFileFromStorageFile(storageFile);
var url = URL.createObjectURL(file, { oneTimeOnly: true });
// assume that this.imageElement points to the image tag
self.imageElement.setAttribute('src', url);
}).then(null, function onerror(error)
{
});
refer the link in case you are looking for upload the blob to azure. For send the blob to your webservice also, code will be on these lines.
URL.createObjectURL("") should work. I use it all the time. Test it with some other URLs. You could do it in debug mode in the JS console to make it easier.

How to give a Blob uploaded as FormData a file name?

I am currently uploading images pasted from the clipboard with the following code:
// Turns out getAsFile will return a blob, not a file
var blob = event.clipboardData.items[0].getAsFile(),
form = new FormData(),
request = new XMLHttpRequest();
form.append("blob",blob);
request.open(
"POST",
"/upload",
true
);
request.send(form);
Turns out the uploaded form field with receive a name similar to this: Blob157fce71535b4f93ba92ac6053d81e3a
Is there any way to set this or receive this file name client side, without doing any server side communication?
For Chrome, Safari and Firefox, just use this:
form.append("blob", blob, filename);
(see MDN documentation)
Adding this here as it doesn't seem to be here.
Aside from the excellent solution of form.append("blob",blob, filename); you can also turn the blob into a File instance:
var blob = new Blob([JSON.stringify([0,1,2])], {type : 'application/json'});
var fileOfBlob = new File([blob], 'aFileName.json');
form.append("upload", fileOfBlob);
Since you're getting the data pasted to clipboard, there is no reliable way of knowing the origin of the file and its properties (including name).
Your best bet is to come up with a file naming scheme of your own and send along with the blob.
form.append("filename",getFileName());
form.append("blob",blob);
function getFileName() {
// logic to generate file names
}
That name looks derived from an object URL GUID. Do the following to get the object URL that the name was derived from.
var URL = self.URL || self.webkitURL || self;
var object_url = URL.createObjectURL(blob);
URL.revokeObjectURL(object_url);
object_url will be formatted as blob:{origin}{GUID} in Google Chrome and moz-filedata:{GUID} in Firefox. An origin is the protocol+host+non-standard port for the protocol. For example, blob:http://stackoverflow.com/e7bc644d-d174-4d5e-b85d-beeb89c17743 or blob:http://[::1]:123/15111656-e46c-411d-a697-a09d23ec9a99. You probably want to extract the GUID and strip any dashes.
Haven't tested it, but that should alert the blobs data url:
var blob = event.clipboardData.items[0].getAsFile(),
form = new FormData(),
request = new XMLHttpRequest();
var reader = new FileReader();
reader.onload = function(event) {
alert(event.target.result); // <-- data url
};
reader.readAsDataURL(blob);
It really depends on how the server on the other side is configured and with what modules for how it handles a blob post. You can try putting the desired name in the path for your post.
request.open(
"POST",
"/upload/myname.bmp",
true
);
Are you using Google App Engine?
You could use cookies (made with JavaScript) to maintain a relationship between filenames and the name received from the server.
When you are using Google Chrome you can use/abuse the Google Filesystem API for this. Here you can create a file with a specified name and write the content of a blob to it. Then you can return the result to the user.
I have not found a good way for Firefox yet; probably a small piece of Flash like downloadify is required to name a blob.
IE10 has a msSaveBlob() function in the BlobBuilder.
Maybe this is more for downloading a blob, but it is related.

Categories

Resources