I'm trying to write a Base64 image into device storage using HTML2Canvas and Cordova ExternalDirectory.
The image file is created but it's broken. When I opened the blob image using BlobUrl function it works fine in a new window.
Note: Required permission is added in Android Manifest
Sample code below
var blobUrl;
function customB64toBlob(b64Data) {
console.log(" ----- b64Data ----");
var parts = b64Data.split(";");
var contentType = parts[0].split(":")[1];
var realData = parts[1].split(",")[1];
console.log(parts);
console.log("Real data");
contentType = contentType || '';
sliceSize = 512;
var byteCharacters = atob(realData);
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});
blobUrl = URL.createObjectURL(blob);
console.log(blob);
return blob;
}
function savebase64AsImageFile(folderpath,filename,content){
// Convert the base64 string in a Blob
var dataBlob = customB64toBlob(content);
console.log(" ----- Writing file ----");
window.resolveLocalFileSystemURL(folderpath, function(dir) {
console.log("Access to the directory granted succesfully");
dir.getFile(filename, {create:true}, function(file) {
console.log("File created succesfully.");
file.createWriter(function(fileWriter) {
console.log("Writing content to file");
fileWriter.write(dataBlob);
}, function(){
alert('Unable to save file in path '+ folderpath);
});
});
});
}
this.savebase64AsImageFile(cordova.file.externalDataDirectory, 'Test.png', base64Canvas);
window.open(blobUrl);
When I opened in New window using Bloburl - Output here
But After writing the image file, this is the result
I created a separate plugin for Save the file [Native level] into the device for both Android and IOS in cordova. I feel there is an issue with the existing filewriter plugin
JAVA
private Boolean saveImage(final CallbackContext callbackContext, final String bs64String) {
cordova.getThreadPool().execute(new SocialSharingRunnable(callbackContext) {
public void run() {
//Directory and File
try {
String dirName = webView.getContext().getExternalFilesDir(null) + "/";
File dir = new File(dirName);
File file = new File(dirName, cordova.getActivity().getApplicationContext().getString(R.string.filename)+".png");
Log.d("SaveFile", "Save Image");
Log.d("SaveFile", "dirName "+dirName);
//Avoid overwriting a file
/* if (!overwrite && file.exists()) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, "File already exists!"));
}*/
//Decode Base64 back to Binary format
byte[] decodedBytes = Base64.decode(bs64String.getBytes(), Base64.DEFAULT);
//Save Binary file to phone
file.createNewFile();
FileOutputStream fOut = new FileOutputStream(file);
fOut.write(decodedBytes);
fOut.close();
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, "Saved successfully!"));
} catch (FileNotFoundException e) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "File not Found!"));
} catch (IOException e) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.getMessage()));
}
}
});
return true;
}
IOS
- (void)saveImage:(CDVInvokedUrlCommand*)command {
CDVPluginResult *pluginResult;
@try
{
NSLog(@"========== saveImage ========");
NSString* strBase64Img = [command.arguments objectAtIndex:0];
NSLog(@"strBase64Img %@",strBase64Img);
NSData *imageData = [Sharing dataFromBase64String:strBase64Img];
UIImage *image = [UIImage imageWithData:imageData];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSLog(@"paths %@",paths);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(@"documentsDirectory %@",documentsDirectory);
NSString *getImagePath = [documentsDirectory stringByAppendingPathComponent:@"ImageName.png"];
[UIImagePNGRepresentation(image) writeToFile:getImagePath atomically:YES];
NSString *savedImage = @"Successfully saved";
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:savedImage];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@catch(id anException) {
NSString *failImg = @"Failed to Save";
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:failImg];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
}
JAVASCRIPT
cordova.exec(onSaveSuccess, onSaveError, "Sharing", "saveImage", [base64Canvas]);