I'm converting canvas to dataURL(base64) type and I wanted to save it to phone filesystem using PhoneGap's writer but without success (I get broken file which I cannot open) - here's some of my code:
var dataURL = document.getElementById("gen").toDataURL('image/png'); //substr() .replace('datadata:image/png;base64,', '');
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
function gotFS(fileSystem) {
fileSystem.root.getFile("screenshot.png", {create: true, exclusive: false}, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
fileEntry.createWriter(gotFileWriter, fail);
}
function gotFileWriter(writer) {
console.log("open and write");
writer.seek(0);
writer.write(dataURL);
console.log("close and save");
}
function fail(error) {
console.log(error.code);
}
var fileTransfer = new FileTransfer();
fileTransfer.download("/", screenshot.png,
function(entry) {
alert("download complete");
},
function(error) {
alert("download error source " + error.source);
alert("download error target " + error.target);
alert("upload error code" + error.code);
}
);
I've tried also other solution from stackoverflow, which was based on addtional java plugin but it hasn't work for me. Is there pure JS(with additional js libs) solution for it?
You may need to request larger file quota for the file system that is big enough to hold the image. Default is typically 5 mb but may vary in the different browsers as it's not standarized.
If the length of the data-uri exceeds this (which is likely considering it's a PNG file with 33% added 33% overhead as base64) the file won't save properly.
You can request quota using the quota API:
webkitStorageInfo.requestQuota(
webkitStorageInfo.PERSISTENT
newQuotaInBytes,
quotaCallback,
errorCallback);
More details can be found here.
FileWriter’s write method does not take a base64 string.
According to the docs (http://docs.phonegap.com/en/edge/cordova_file_file.md.html#FileWriter)
text will be encoded as UTF-8 before being written. So your base64 string is being encoded before writing to the file so it’s not valid image data.
You have to pass your image data as a Blob or an ArrayBuffer. Note this only works on iOS and Android.
Have a look at Jeremy Banks’ b64toBlob function in this answer: https://stackoverflow.com/a/16245768
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
You can pass the resulting blob into the write method.
You also have to take into account that you are getting a base64 encoded picture, so you cannot just save the as an images file an expect it to be a image.
So you have to Base64 decode that first before it will be an image. Maybe look at atob to do that
https://developer.mozilla.org/en-US/docs/Web/API/Window.atob