Saving dataURL(base64) to file on PhoneGap (androi

2019-01-26 15:02发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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