Search code examples
javascriptangularjscordovaphonegap-pluginscordova-plugins

Can you save base64 data as a file with ngCordova?


In this tutorial, the author uses the FileURI to copy the image from the temporary location to the device location, and finally returning the nativeURL of this copied file.

window.resolveLocalFileSystemURL(fileURI, success, fail);

Instead of the FileURI I have a base64 string (imageData) which I want to save also on the device location and return the nativeURL of this saved image.

Is this possible and how would one achieve this with ngCordova?

1. draw on canvas in controller

$scope.drawAndSave = function() {

    $scope.targetImages = [{nativeURL: "img/newyork.jpg"}, {nativeURL: "img/newyork.jpg"}]

    drawCanvas().then(function(data){
      $scope.outputImages = data; // works fine, can save it

      for (var i = 0; i < data.length; i++) { 
        FileFactory.saveCanvasToDataUrl(data[i])
      }

    });

    function drawCanvas() {
      var pResults = $scope.targetImages.map(function (imageObj) {
        return drawToCanvas(imageObj.nativeURL);
      });
      return $q.all(pResults);
    }

    function drawToCanvas(nativeURL) {
      return $q(function (resolve) {
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var img = new Image();
        img.src = nativeURL;

        img.onload = function () {
            ctx.drawImage(img, 0, 0);
            resolve(canvas.toDataURL("image/jpeg"));
        };

      });
    } // draw to canvas

  }

2. save canvas as image with for the input fileURI the canvas.toDataUrl() dataURI.

.factory('FileFactory', function($cordovaFile, $q) {

    var saveCanvasToDataUrl = function(imageData) {
        copyFileURI(imageData) 
    }

    // // http://devdactic.com/how-to-capture-and-store-images-with-ionic/
    // todo: get file uri and copy it
    var copyFileURI = function(fileURI) {

        window.alert("saving ")

        var q = $q.defer();
        onImageSuccess(fileURI);
        function onImageSuccess(fileURI) {
            createFileEntry(fileURI);
        }
        function createFileEntry(fileURI) {
            window.resolveLocalFileSystemURL(fileURI, copyFile, fail);
        }
        function copyFile(fileEntry) {
            var name = fileEntry.fullPath.substr(fileEntry.fullPath.lastIndexOf('/') + 1);
            var newName = makeid() + name;
            window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function(fileSystem2) {
                fileEntry.copyTo(
                    fileSystem2,
                    newName,
                    onCopySuccess,
                    fail
            );
            },
            fail);
        }
        function onCopySuccess(entry) {
            q.resolve(entry.nativeURL) 
        }
        function fail(error) {
            q.reject(error)
            window.alert("fail: " + JSON.stringify(error))
        }
        function makeid() {
            var text = "";
            var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            for (var i=0; i < 5; i++) {
            text += possible.charAt(Math.floor(Math.random() * possible.length));
            }
            return text;
        }

        return q.promise;
    } // copy file uri, return new native url


    var removeFile = function(nativeURL) {

        var name = nativeURL.substr(nativeURL.lastIndexOf('/') + 1);
        window.alert("trying to delete nativeURL name: " + nativeURL)
        window.alert("cordova file directory: " + cordova.file.dataDirectory)
        window.alert('name: ' + name)

        $cordovaFile.checkFile(cordova.file.dataDirectory, name)
        .then(function (success) {

            window.alert("file found " + success)

            $cordovaFile.removeFile(cordova.file.dataDirectory, name)
                .then(function (success) {
                    // success
                    window.alert("file deleted " + success)
                }, function (error) {
                // error
                window.alert("file not deleted error " + error)
                });

        }, function (error) {
        // error
            window.alert("file not ound " + JSON.stringify(error))
        });

    }

    return {
        copyFileURI: copyFileURI, 
        removeFile: removeFile,
        saveCanvasToDataUrl: saveCanvasToDataUrl
    }

});

Solution

  • Try following code to save base64 string to file

    // I assume your base64 string is stored in a variable 'imageData'
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
    function gotFS(fileSystem) {
        fileSystem.root.getFile("image.jpg", {create: true, exclusive: false}, gotFileEntry, fail);
    }
    function gotFileEntry(fileEntry) {
        fileEntry.createWriter(gotFileWriter, fail);
    }
    function gotFileWriter(writer) {
        console.log("Start creating image file");
        writer.seek(0);
        writer.write(imageData);
        console.log("End creating image file. File created");
    }
    

    Grouping all the above into a function

    function savefile(dataurl){
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, 
        function (fileSystem) {
            fileSystem.root.getFile("image.jpg", {create: true, exclusive: false}, 
                function (fileEntry) {
                    fileEntry.createWriter(function (writer) {
                        console.log("Start creating image file");
                        writer.seek(0);
                        writer.write(dataurl);
                        console.log("End creating image file. File created");
                    }, fail);
                }, fail);
        }, fail);
    }
    
    function fail(){
        console.log("Error");
    }
    

    Now you can call the function by savefile(dataurl) where dataurl is the base64 string

    Updated:

    Above version didn't had the folder selection. In below function app_folder_name variable has to be replace to folder in device.

    function savefile(dataurl){
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, 
        function (fileSystem) {
            fileSystem.root.getDirectory( app_folder_name, {create:true, exclusive: false},
            function(directory) {
                directory.root.getFile("image.jpg", {create: true, exclusive: false}, 
                function (fileEntry) {
                    fileEntry.createWriter(function (writer) {
                        console.log("Start creating image file");
                        writer.seek(0);
                        writer.write(dataurl);
                        console.log("End creating image file. File created");
                    }, fail);
                }, fail);
            }, fail);
        }, fail);
    }