Using FileReader's readAsDataURL() I can transform arbitrary data into a Data URL. Is there way to convert a Data URL back into a Blob instance using builtin browser apis?
User Matt has proposed the following code a year ago ( How to convert dataURL to file object in javascript? ) which might help you
EDIT: As some commenters reported, BlobBuilder has been deprecated some time ago. This is the updated code:
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
// create a view into the buffer
var ia = new Uint8Array(ab);
// set the bytes of the buffer to the correct values
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {type: mimeString});
return blob;
}
Like #Adria method but with Fetch api and just smaller [caniuse?]
Don't have to think about mimetype since blob response type just works out of the box
Warning: Can violate the Content Security Policy (CSP)
...if you use that stuff
var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
fetch(url)
.then(res => res.blob())
.then(blob => console.log(blob))
Don't think you could do it any smaller then this without using lib's
In modern browsers one can use the one liner suggested by Christian d'Heureuse in a comment:
const blob = await (await fetch(dataURI)).blob();
dataURItoBlob : function(dataURI, dataTYPE) {
var binary = atob(dataURI.split(',')[1]), array = [];
for(var i = 0; i < binary.length; i++) array.push(binary.charCodeAt(i));
return new Blob([new Uint8Array(array)], {type: dataTYPE});
}
input dataURI is Data URL and dataTYPE is the file type and then output blob object
XHR based method.
function dataURLtoBlob( dataUrl, callback )
{
var req = new XMLHttpRequest;
req.open( 'GET', dataUrl );
req.responseType = 'arraybuffer'; // Can't use blob directly because of https://crbug.com/412752
req.onload = function fileLoaded(e)
{
// If you require the blob to have correct mime type
var mime = this.getResponseHeader('content-type');
callback( new Blob([this.response], {type:mime}) );
};
req.send();
}
dataURLtoBlob( 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', function( blob )
{
console.log( blob );
});
try:
function dataURItoBlob(dataURI) {
if(typeof dataURI !== 'string'){
throw new Error('Invalid argument: dataURI must be a string');
}
dataURI = dataURI.split(',');
var type = dataURI[0].split(':')[1].split(';')[0],
byteString = atob(dataURI[1]),
byteStringLength = byteString.length,
arrayBuffer = new ArrayBuffer(byteStringLength),
intArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteStringLength; i++) {
intArray[i] = byteString.charCodeAt(i);
}
return new Blob([intArray], {
type: type
});
}
Since none of these answers support base64 and non-base64 dataURLs, here's one that does based on vuamitom's deleted answer:
// from https://stackoverflow.com/questions/37135417/download-canvas-as-png-in-fabric-js-giving-network-error/
var dataURLtoBlob = exports.dataURLtoBlob = function(dataurl) {
var parts = dataurl.split(','), mime = parts[0].match(/:(.*?);/)[1]
if(parts[0].indexOf('base64') !== -1) {
var bstr = atob(parts[1]), n = bstr.length, u8arr = new Uint8Array(n)
while(n--){
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], {type:mime})
} else {
var raw = decodeURIComponent(parts[1])
return new Blob([raw], {type: mime})
}
}
Note: I'm not sure if there are other dataURL mime types that might have to be handled differently. But please let me know if you find out! Its possible that dataURLs can simply have any format they want, and in that case it'd be up to you to find the right code for your particular use case.
Create a blob using XHR API:
function dataURLtoBlob( dataUrl, callback )
{
var req = new XMLHttpRequest;
req.open( 'GET', dataUrl );
req.responseType = 'blob';
req.onload = function fileLoaded(e)
{
callback(this.response);
};
req.send();
}
var dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
dataURLtoBlob(dataURI , function( blob )
{
console.log( blob );
});
If you need something that works server-side on Google Apps Script, try:
function dataURItoBlob(dataURI) {
// convert base64 to Byte[]
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var data = Utilities.base64Decode(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
var blob = Utilities.newBlob(data);
blob.setContentType(mimeString);
return blob;
}
use
FileReader.readAsArrayBuffer(Blob|File)
rather than
FileReader.readAsDataURL(Blob|File)
Related
Struggling to convert a base64 image captured using a webcam into a jpeg for upload.
The following capture / display photo works (note that I am using webcam.min.js (which returns base64) and not webcam.js (which returns jpeg but relies on Flash) -
function take_snapshot() {
Webcam.snap( function(data_uri) {
// display results in page
document.getElementById('upload_results').innerHTML =
'<img id="imageprev" src="'+data_uri+'"/>';
} );
}
I have tried the following, which may or may not be converting the base 64image to a blob -
function saveSnap(){
var base64image = document.getElementById("imageprev").src;
alert(base64image)
// convert base64 to raw binary data held in a string
var byteString = atob(base64image.split(',')[1]);
// separate out the mime component
var mimeString = base64image.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var dw = new DataView(ab);
for(var i = 0; i < byteString.length; i++) {
dw.setUint8(i, byteString.charCodeAt(i));
alert("arrived here");
// write the ArrayBuffer to a blob, and you're done
return new Blob([ab], {type: mimeString});
}
And this doesn't do anything, except halt the jsp
let image = new Image();
image.src = base64image;
document.body.appendChild(image);
How do I get / see / extract the actual jpeg file so I can then upload it
(it must be something like number.jpeg)
JDK6 / Javascript (no php please)
Any thoughts appreciated.
Regards
Ralph
Create an image object and put the base64 as its source.
let image = new Image();
image.src = 'data:image/png;base64,iVBORw0K...';
document.body.appendChild(image);
var aFilePartss = [image];
var oMyBlob = new Blob(aFileParts, {type : 'image/png'});
// window.open(URL.createObjectURL(oMyBlob));
var fd = new FormData();
fd.append('data', oMyBlob);
$.ajax({
type: 'POST',
url: '/upload.php',
data: fd,
}).done(function(data) {
console.log(data);
});
Here is the basics you need to convert to blob and upload.
const MOCK_DATA_URL = `data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEVBMTczNDg3QzA5MTFFNjk3ODM5NjQyRjE2RjA3QTkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEVBMTczNDk3QzA5MTFFNjk3ODM5NjQyRjE2RjA3QTkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowRUExNzM0NjdDMDkxMUU2OTc4Mzk2NDJGMTZGMDdBOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowRUExNzM0NzdDMDkxMUU2OTc4Mzk2NDJGMTZGMDdBOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjjUmssAAAGASURBVHjatJaxTsMwEIbpIzDA6FaMMPYJkDKzVYU+QFeEGPIKfYU8AETkCYI6wANkZQwIKRNDB1hA0Jrf0rk6WXZ8BvWkb4kv99vn89kDrfVexBSYgVNwDA7AN+jAK3gEd+AlGMGIBFDgFvzouK3JV/lihQTOwLtOtw9wIRG5pJn91Tbgqk9kSk7GViADrTD4HCyZ0NQnomi51sb0fUyCMQEbp2WpU67IjfNjwcYyoUDhjJVcZBjYBy40j4wXgaobWoe8Z6Y80CJBwFpunepIzt2AUgFjtXXshNXjVmMh+K+zzp/CMs0CqeuzrxSRpbOKfdCkiMTS1VBQ41uxMyQR2qbrXiiwYN3ACh1FDmsdK2Eu4J6Tlo31dYVtCY88h5ELZIJJ+IRMzBHfyJINrigNkt5VsRiub9nXICdsYyVd2NcVvA3ScE5t2rb5JuEeyZnAhmLt9NK63vX1O5Pe8XaPSuGq1uTrfUgMEp9EJ+CQvr+BJ/AAKvAcCiAR+bf9CjAAluzmdX4AEIIAAAAASUVORK5CYII=`
function takeSnapshotThenUpload() {
//get datauri
let blob = convertToBlob(MOCK_DATA_URL)
return uploadFile(blob)
}
function convertToBlob(base64image) {
// convert base64 to raw binary data held in a string
var byteString = atob(base64image.split(',')[1]);
// separate out the mime component
var mimeString = base64image.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var dw = new DataView(ab);
for (var i = 0; i < byteString.length; i++) {
dw.setUint8(i, byteString.charCodeAt(i));
alert("arrived here");
// write the ArrayBuffer to a blob, and you're done
return new Blob([ab], {
type: mimeString
});
}
}
function uploadFile(blob) {
const formData = new FormData()
formData.append('cancel.jpeg', blob)
fetch('/saveImage', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
console.log(data)
})
.catch(error => {
console.error(error)
})
}
<button onclick="takeSnapshotThenUpload()">Take screenshot then upload</button>
Remember to fix your takeSnapshotThenUpload to something like:
<script src="webcam.js"></script>
<div id="my_camera" style="width:320px; height:240px;"></div>
<div id="my_result"></div>
<script language="JavaScript">
Webcam.attach( '#my_camera' );
function take_snapshot() {
Webcam.snap( function(data_uri) {
takeSnapshotThenUpload(data_uri)
} );
}
</script>
Take Snapshot
Example code for converting base64 to file (image/jpeg):
async base64ToFile(base64) {
const res = await fetch(base64)
const buf = await res.arrayBuffer()
const file = new File([buf], "capture_camera.jpeg", {
type: 'image/jpeg',
})
return file;
};
I always get this error in the downloaded zip file C:\Users\me\Downloads\test.zip: Unexpected end of archive
My current code is:
var blob = new Blob([data], { // data here is the binary content
type: 'octet/stream',
});
var zipUrl = window.URL.createObjectURL(blob);
var fileName = orderNo;
fileName += '.zip';
downloadFile(null, fileName, null, zipUrl, null); // just creates a hidden anchor tag and triggers the download
The response of the call is a binary (I think). Binary Content Here
But the preview is a base64. Base64 Content. And it is the correct one. The way I verify it is by using this fiddle.
You can refer to the screenshot of the network here
I put the base64 content in this line var sampleBytes = base64ToArrayBuffer(''); And the zip downloaded just opens fine.
Things I have tried so far.
Adding this headers to the GET call
var headers = {
Accept: 'application/octet-stream',
responseType: 'blob',
};
But I get Request header field responseType is not allowed by Access-Control-Allow-Headers in preflight response.
We're using an already ajax.service.js in our AngularJS project.
From this answer
var blob = new Blob([yourBinaryDataAsAnArrayOrAsAString], {type: "application/octet-stream"});
var fileName = "myFileName.myExtension";
saveAs(blob, fileName);
There are other things that I have tried that I have not listed. I will edit the questions once I find them again
But where I'm current at right now. The preview is correct base64 of the binary file. Is it possible to use that instead of the binary? (If it is I will not find the other methods that I've tested) I tried some binary to base64 converters but they don't work.
So I just went and ditched using the ajax.service.js, that we have, for this specific call.
I used the xhr snippet from this answer. I just added the headers necessary for our call: tokens and auth stuff.
And I used this code snippet for the conversion thing.
And the code looks like this:
fetchBlob(url, function (blob) {
// Array buffer to Base64:
var base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(blob)));
var blob = new Blob([base64ToArrayBuffer(base64)], {
type: 'octet/stream',
});
var zipUrl = window.URL.createObjectURL(blob);
var fileName = orderNo;
fileName += ' Attachments ';
fileName += moment().format('DD-MMM-YYYY');
fileName += '.zip';
downloadFile(null, fileName, null, zipUrl, null); // create a hidden anchor tag and trigger download
});
function fetchBlob(uri, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', uri, true);
xhr.responseType = 'arraybuffer';
var x = AjaxService.getAuthHeaders();
xhr.setRequestHeader('auth_stuff', x['auth_stuff']);
xhr.setRequestHeader('token_stuff', x['token_stuff']);
xhr.setRequestHeader('Accept', 'application/octet-stream');
xhr.onload = function (e) {
if (this.status == 200) {
var blob = this.response;
if (callback) {
callback(blob);
}
}
};
return xhr.send();
};
function base64ToArrayBuffer(base64) {
var binaryString = window.atob(base64);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
};
return bytes;
}
I have used HTML file reader API to read the file,
and i got the below result
data:application/pdf;base64,JVBERi0xLjYNJeLjz9MNCjE2OSAwIG9iaiA8PC9MaW5lYXJpemVkIDEvTCAyMDgwNTMxL08gMTczL0UgMjg1ODM3L04gMjQvVCAyMDc3MDkyL0ggWyAxMTM2IDc1OV0+Pg1lbmRvYmoNICAgICAgICAgIA14cmVmDTE2OSA0Mg0wMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDE4OTUgMDAwMDAgbg0KMDAwMDAwMjAzMSAwMDAwMCBuDQowMDAwMDAyMTY0IDAwMDAwIG4NCjAwMDAwMDIzMTkgMDAwMDAgbg0KMDAwMDAwMjgzOCAwMDAwMCBuDQowMDAwMDAyODY0IDAwMDAwIG4NCjAwMDAwMDM3OTAgMDAwMDAgbg0KMDAwMDAwNDMyNCAwMDAwMCBuDQowMDAwMDA0NDE1IDAwMDAwIG4NCjAwMDAwMDU2MDcgMDAwMDAgbg0KMDAwMDAwNTY1MiAwMDAwMCBuDQowMDAwMDA1Njc3IDAwMDAwIG4NCjAwMDAwMDU3OTUgMDAwMDAgbg0KMDAwMDAwNTg0NSAwMDAwMCBuDQowMDAwMDA1ODcwIDAwMDAwIG4NCjAwMDAwMDU5ODYgMDAwMDAgbg0KMDAwMDAwNzQxOSAwMDAwMCBuDQowMDAwMDA3Nzk4IDAwMDAwIG4NCjAwMDAwMDgxMDQgMDAwMDAgbg0KMDAwMDAwODQxMyAwMDAwMCBuDQowMDAwMDA4OTQ0IDAwMDAwIG4NCjAwMDAwMDk2NTAgMDAwMDAgbg0KMDAwMDAxMDA1NiAwMDAwMCBuDQowMDAwMDEwMjIxIDAwMDAwIG4NCjAwMDAwMTA1NDIgMDAwMDAgbg0KMDAwMDAxMDc1MCAwMDAwMCBuDQowMDAwMDExMDM1IDAwMDAwIG4NCjAwMDAwMTEwOTYgMDAwMDAgbg0KMDAwMDAxMTQxMiAwMDAwMCBuDQo...AwMDAwIG4NCjAwMDIwNTkxMzggMDAwMDAgbg0KMDAwMjA2MjUxMyAwMDAwMCBuDQowMDAyMDYyOTE4IDAwMDAwIG4NCjAwMDIwNjI5NjYgMDAwMDAgbg0KMDAwMjA2MzMyNSAwMDAwMCBuDQowMDAyMDYzNDEyIDAwMDAwIG4NCjAwMDIwNjM2NDggMDAwMDAgbg0KMDAwMjA2NDU0NiAwMDAwMCBuDQowMDAyMDY1NTU0IDAwMDAwIG4NCjAwMDIwNjU1NzMgMDAwMDAgbg0KMDAwMjA2NTY1MCAwMDAwMCBuDQowMDAyMDY1Njg3IDAwMDAwIG4NCjAwMDIwNjU3MTggMDAwMDAgbg0KMDAwMjA2NTc4OSAwMDAwMCBuDQowMDAyMDY1OTIxIDAwMDAwIG4NCjAwMDIwNjYwNTMgMDAwMDAgbg0KMDAwMjA2NjE0NSAwMDAwMCBuDQowMDAyMDY2MjAyIDAwMDAwIG4NCjAwMDIwNjk5MDEgMDAwMDAgbg0KMDAwMjA2OTk1MSAwMDAwMCBuDQowMDAyMDcwMDE3IDAwMDAwIG4NCjAwMDIwNzAwNDkgMDAwMDAgbg0KMDAwMjA3MDA5OCAwMDAwMCBuDQowMDAyMDcwMTQyIDAwMDAwIG4NCjAwMDIwNzAxODggMDAwMDAgbg0KMDAwMjA3MDIxMCAwMDAwMCBuDQowMDAyMDcwMjc5IDAwMDAwIG4NCjAwMDIwNzAzMTcgMDAwMDAgbg0KMDAwMjA3MDM3NSAwMDAwMCBuDQowMDAyMDcwNDk5IDAwMDAwIG4NCjAwMDIwNzA1MzEgMDAwMDAgbg0KMDAwMjA3MDU1MiAwMDAwMCBuDQowMDAyMDcwNTc4IDAwMDAwIG4NCjAwMDIwNzY4NDMgMDAwMDAgbg0KdHJhaWxlcg08PC9TaXplIDE2OS9FbmNyeXB0IDE3MCAwIFI+Pg1zdGFydHhyZWYNMTE2DSUlRU9GDQ==
How to write a file and force download the same file using the above string?
Warning: I don't have IE available to test with, but this was based off code that DOES work under IE.
My DataURL is an image so I had to change out the header. You might not have to with your header -- but I left the code in place so you could see how it was done.
Thanks to IE, you need two different processes.
On IE, you convert your DataURI to a blob then download the blob.
On everything else, you would just download the URI itself.
document.getElementById("d_button").addEventListener("click", download);
var filename="testfile";
// FROM http://stackoverflow.com/questions/12168909/blob-from-dataurl
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {
type: mimeString
});
return blob;
// Old code
// var bb = new BlobBuilder();
// bb.append(ab);
// return bb.getBlob(mimeString);
}
const dataURI = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
function download() {
if (window.navigator.msSaveBlob) { // for IE
const blob = dataURItoBlob(dataURI);
window.navigator.msSaveBlob(blob, `${filename}.png`);
return;
}
let dt = dataURI;
/* Change MIME type to trick the browser to downlaod the file instead of displaying it */
dt = dt.replace(/^data:image\/[^;]*/, "data:application/octet-stream");
/* In addition to <a>'s "download" attribute, you can define HTTP-style headers */
dt = dt.replace(/^data:application\/octet-stream/, `data:application/octet-stream;headers=Content-Disposition%3A%20attachment%3B%20filename=${filename}.png`);
this.href = dt;
}
Download this
I got answer using <a> tag force the download the file.
var element = document.createElement('a');
element.setAttribute('href',text );
element.setAttribute('download', filename);
element.setAttribute('target', '_blank');
element.style.display = 'none';
document.body.appendChild(element);
$("#page_header").removeClass('loader');
element.click();
I got another answer using force the download the file.
using this link install file saver (https://www.npmjs.com/package/file-saver)
result : 'data:application/pdf;base64,JVBERi0xLjYNJeLjz9MNCjE2OSAwIG9iaiA8PC9MaW5lYXJpemVkIDEvTCAyMDgwNTMxL08gMTczL0UgMjg1ODM3L04gMjQvVCAyMDc3MDkyL0ggWyAxMTM2IDc1OV0+Pg1lbmRvYmoNICAgICAgICAgIA14cmVmDTE2OSA0Mg0wMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDE4OTUgMDAwMDAgbg0KMDAwMDAwMjAzMSAwMDAwMCBuDQowMDAwMDAyMTY0IDAwMDAwIG4NCjAwMDAwMDIzMTkgMDAwMDAgbg0KMDAwMDAwMjgzOCAwMDAwMCBuDQowMDAwMDAyODY0IDAwMDAwIG4NCjAwMDAwMDM3OTAgMDAwMDAgbg0KMDAwMDAwNDMyNCAwMDAwMCBuDQowMDAwMDA0NDE1IDAwMDAwIG4NCjAwMDAwMDU2MDcgMDAwMDAgbg0KMDAwMDAwNTY1MiAwMDAwMCBuDQowMDAwMDA1Njc3IDAwMDAwIG4NCjAwMDAwMDU3OTUgMDAwMDAgbg0KMDAwMDAwNTg0NSAwMDAwMCBuDQowMDAwMDA1ODcwIDAwMDAwIG4NCjAwMDAwMDU5ODYgMDAwMDAgbg0KMDAwMDAwNzQxOSAwMDAwMCBuDQowMDAwMDA3Nzk4IDAwMDAwIG4NCjAwMDAwMDgxMDQgMDAwMDAgbg0KMDAwMDAwODQxMyAwMDAwMCBuDQowMDAwMDA4OTQ0IDAwMDAwIG4NCjAwMDAwMDk2NTAgMDAwMDAgbg0KMDAwMDAxMDA1NiAwMDAwMCBuDQowMDAwMDEwMjIxIDAwMDAwIG4NCjAwMDAwMTA1NDIgMDAwMDAgbg0KMDAwMDAxMDc1MCAwMDAwMCBuDQowMDAwMDExMDM1IDAwMDAwIG4NCjAwMDAwMTEwOTYgMDAwMDAgbg0KMDAwMDAxMTQxMiAwMDAwMCBuDQo...AwMDAwIG4NCjAwMDIwNTkxMzggMDAwMDAgbg0KMDAwMjA2MjUxMyAwMDAwMCBuDQowMDAyMDYyOTE4IDAwMDAwIG4NCjAwMDIwNjI5NjYgMDAwMDAgbg0KMDAwMjA2MzMyNSAwMDAwMCBuDQowMDAyMDYzNDEyIDAwMDAwIG4NCjAwMDIwNjM2NDggMDAwMDAgbg0KMDAwMjA2NDU0NiAwMDAwMCBuDQowMDAyMDY1NTU0IDAwMDAwIG4NCjAwMDIwNjU1NzMgMDAwMDAgbg0KMDAwMjA2NTY1MCAwMDAwMCBuDQowMDAyMDY1Njg3IDAwMDAwIG4NCjAwMDIwNjU3MTggMDAwMDAgbg0KMDAwMjA2NTc4OSAwMDAwMCBuDQowMDAyMDY1OTIxIDAwMDAwIG4NCjAwMDIwNjYwNTMgMDAwMDAgbg0KMDAwMjA2NjE0NSAwMDAwMCBuDQowMDAyMDY2MjAyIDAwMDAwIG4NCjAwMDIwNjk5MDEgMDAwMDAgbg0KMDAwMjA2OTk1MSAwMDAwMCBuDQowMDAyMDcwMDE3IDAwMDAwIG4NCjAwMDIwNzAwNDkgMDAwMDAgbg0KMDAwMjA3MDA5OCAwMDAwMCBuDQowMDAyMDcwMTQyIDAwMDAwIG4NCjAwMDIwNzAxODggMDAwMDAgbg0KMDAwMjA3MDIxMCAwMDAwMCBuDQowMDAyMDcwMjc5IDAwMDAwIG4NCjAwMDIwNzAzMTcgMDAwMDAgbg0KMDAwMjA3MDM3NSAwMDAwMCBuDQowMDAyMDcwNDk5IDAwMDAwIG4NCjAwMDIwNzA1MzEgMDAwMDAgbg0KMDAwMjA3MDU1MiAwMDAwMCBuDQowMDAyMDcwNTc4IDAwMDAwIG4NCjAwMDIwNzY4NDMgMDAwMDAgbg0KdHJhaWxlcg08PC9TaXplIDE2OS9FbmNyeXB0IDE3MCAwIFI+Pg1zdGFydHhyZWYNMTE2DSUlRU9GDQ=='
file_name : 'sample.jpg'
fileType : 'image/jpeg'
**Function Call**
this.urltoFile(result, file_name, fileType)
.then(function(file){
var blob = new Blob ([file], {type: fileType});
FileSaver.saveAs(blob, file_name);
this.loading = false;
});
**function definition**
urltoFile(url, filename, mimeType){
return (fetch(url)
.then(function(res){return res.arrayBuffer();})
.then(function(buf){return new File([buf], filename, {type:mimeType});})
)},
I have converted an image into dataurl using FileReader and it gives me output like:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlā¦Vp1m8u4+SV/s0TpD8+91R/3Xlf8sXZv9Y9OGLk5eyVnCNu19Ntdu2jYOnaHtG7ffb7t/uP/9k=
Which is a very long string..
Now I again want to convert it to file object so that I can post this image.
How can I again convert this image into file object
Converting dataurl to File Object
https://jsfiddle.net/fn2aonwy/
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
var blob = new Blob([ia], { type: 'image/jpeg' });
var file = new File([blob], "image.jpg");
based on #William-t answer / more discussion on stackoverflow.com/questions/4998908/
MDN blob file
A Blob object represents a file-like object of immutable, raw data.
Blobs represent data that isn't necessarily in a JavaScript-native
format. The File interface is based on Blob, inheriting blob
functionality and expanding it to support files on the user's system.
MDN FormData
var form = new FormData(),
request = new XMLHttpRequest();
form.append("image", blob, "myimage.jpg");
request.open("POST", "/upload", true);
request.send(form);
You can use fetch to convert an url to a File object.
//load src and convert to a File instance object
//work for any type of src, not only image src.
//return a promise that resolves with a File instance
function srcToFile(src, fileName, mimeType){
return (fetch(src)
.then(function(res){return res.arrayBuffer();})
.then(function(buf){return new File([buf], fileName, {type:mimeType});})
);
}
//usage example: (works in Chrome and Firefox)
srcToFile(
'data:image/gif;base64,R0lGODlhDgANAKIAAAAAAP///9HV2U5RU////wAAAAAAAA'
+ 'AAACH5BAEAAAQALAAAAAAOAA0AAAMXSLrc/hCO0Wa1atJLtdTbF0ZjZJ5oyiQAOw==',
'arrow.gif',
'image/gif'
)
.then(function(file){
console.log(file);
})
To make a long story short:
How to Asynchronously write an ArrayBuffer directly to file using nsIArrayBufferInputStream in Firefox extension ?
It seems that MDN does not have any documentation on nsIArrayBufferInputStream.
I know I can use nsIStringInputStream and convert the BufferArray to String, but this poses a big performance hit
also converting ArrayBuffer to string using this code:
String.fromCharCode.apply(null, new Uint16Array(buf));
Does not work if the buffer is 500 KB or bigger, so we must loop over it one char at a time:
for (let i = 0; i < buf.length; i++){
s += String.fromCharCode(buf16[i]);
}
Or, I can use nsIBinaryOutputStream.writeByteArray but it cannot be used with NetUtil.asyncCopy (or can it?)
//this works ok, but is synchronous :-(
function writeBinFile(aFile, data){
Components.utils.import("resource://gre/modules/FileUtils.jsm");
let nsFile = Components.Constructor("#mozilla.org/file/local;1", Ci.nsILocalFile, "initWithPath");
if(typeof aFile === 'string') aFile = nsFile(aFile);
var stream = FileUtils.openSafeFileOutputStream(aFile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE);
var binaryStream = Cc["#mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);
binaryStream.setOutputStream(stream);
binaryStream.writeByteArray(data, data.length);
FileUtils.closeSafeFileOutputStream(stream);
}
And the long story is...
I have been trying to use nsIArrayBufferInputStream
http://dxr.mozilla.org/mozilla-central/source/netwerk/base/public/nsIArrayBufferInputStream.idl
but with no success. the code I tried:
function fileWrite(file, data, callback) {
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
let nsFile = Components.Constructor("#mozilla.org/file/local;1", Ci.nsILocalFile, "initWithPath");
if (typeof file == 'string') file = new nsFile(file);
let ostream = FileUtils.openSafeFileOutputStream(file)
let istream = Cc["#mozilla.org/io/arraybuffer-input-stream;1"].createInstance(Ci.nsIArrayBufferInputStream);
istream.setData(data, 0, data.length);
let bstream = Cc["#mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
bstream.setInputStream(istream);
//NetUtil.asyncCopy(istream, ostream,
NetUtil.asyncCopy(bstream, ostream,
function(status) {
if (callback) callback(Components.isSuccessCode(status));
}
);
}
The ArrayBuffer data param is the responce from XMLHttpRequest:
function getBinFile(url, dir) {
let nsFile = Components.Constructor("#mozilla.org/file/local;1", Ci.nsILocalFile, "initWithPath");
let oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.onload = function(oEvent) {
var arrayBuffer = oReq.response;
if (arrayBuffer) {
//let byteArray = new Uint8Array(arrayBuffer);
let byteArray = arrayBuffer;
dir = /\\$/.test(dir) ? dir: dir + '\\';
let file = nsFile(dir + decodeURIComponent(url.split('/').pop()));
fileWrite(file, byteArray);
}
};
oReq.send(null);
}
calling like this:
getBinFile( 'http://....', 'c:\\demo\\');
A file is created but with no contents!
I'm answering myself in case anyone stumbles upon this question...
with help from Josh Matthews (of Mozilla) i found the answer:
use byteLength instead of length
istream.setData(data, 0, data.byteLength);