Search code examples
javascriptandroidcordovahtml2canvas

Writing the Blob Image using Cordova plugin getting failed [ Android ]


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

enter image description here

But After writing the image file, this is the result

enter image description here


Solution

  • 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]);