0

I have an Angular service with a function for writing files away. The function can work on either an Ionic or Electron platform. For Ionic, it uses $cordovaFile for file actions and for Electron it uses the node fs library.

The function is as follows:

writeFile(filename: string, dirname: string, data: string | Blob, replace?: boolean): ngCordova.IFilePromise<ProgressEvent> {
    if (this.isElectron) {
        let promiseObj = this.$q.defer();
        if (replace) {
            try {
                fs.unlinkSync('./' + dirname + '/' + filename);
            }
            catch (err) {
                //err
            }
        }
        fs.writeFile('./' + dirname + '/' + filename, data, 'binary', () => {
            promiseObj.resolve(true);
        });

        return promiseObj.promise;
    }
    else {
        return this.$cordovaFile.writeFile(cordova.file.dataDirectory + dirname, filename, data, replace);
    }
};

When the Ionic platform is used, the function works fine and the downloaded files are written away correctly. However, when the Electron platform is used, all the downloaded files contain is the string [object Blob].

What is the correct way to write Blobs to files using fs?

MORE INFO

The data originally comes down as base64 in a JSON message but we then do this with it

let fileBlob = this.stringUtilityService.b64ToBlob(dataObj.Data[i].FileContents, 'image/png');

    this.fileSystemService.writeFile(dataObj.Data[i].FileName, 'icons', fileBlob);

EXTRA MORE INFO

Here is the b64ToBlob() function, although as far as i can tell this function works fine and correctly returns a blob which the Ionic app correctly saves away and can display.

b64ToBlob(b64Data: string, contentType: string): any {
        let sliceSize = 512;

        let byteCharacters = atob(b64Data);
        let byteArrays = [];

        for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            let slice = byteCharacters.slice(offset, offset + sliceSize);

            let byteNumbers = new Array(slice.length);
            for (let i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }

            let byteArray = new Uint8Array(byteNumbers);

            byteArrays.push(byteArray);
        }

        let blob = new Blob(byteArrays, { type: contentType });
        return blob;
    }
Jonathan Smith
  • 2,390
  • 1
  • 34
  • 60
  • What kind of data in your code does `data` parameter have? Is it base64 encoded data? – IzumiSy Jan 23 '17 at 15:05
  • Added more info to the original post. – Jonathan Smith Jan 23 '17 at 15:10
  • Got the point. I guess this post would be helpful for you to know how to convert base64 to blob: http://stackoverflow.com/questions/23986953/blob-saved-as-object-object-nodejs – IzumiSy Jan 23 '17 at 15:12
  • We already have the code to convert a base64 string to a blob here: ` this.stringUtilityService.b64ToBlob(dataObj.Data[i].FileContents, 'image/png');` and this code works fine. I just need to know how to write that blob to a file using fs. – Jonathan Smith Jan 23 '17 at 15:30
  • Ok then could you paste the content of the `this.stringUtilityService.b64ToBlob` function? It doesn't look a built-in function. – IzumiSy Jan 23 '17 at 15:35
  • Updated question with b64ToBlob function – Jonathan Smith Jan 23 '17 at 15:45
  • According to the Node.js document, `fs.writeFile` accepts only ` | | ` as data parameter. You need to try to change the acceptable data type, not `Blob`. (https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback) – IzumiSy Jan 23 '17 at 16:07
  • 1
    If you want to post that last comment as a solution, im more than happy to accept it as the answer. Converting it to a Buffer worked. – Jonathan Smith Jan 23 '17 at 17:26

1 Answers1

1

Rewriting b64ToBlob function to the one like the code below would work fine. You need to take out a heading signature string like data:image/gif;base64, if the base64 encoded string has it.

b64ToBlob(b64Data: string): any {
  return Uint8Array.from(atob(b64Data), (c) => c.charCodeAt(0));
}
IzumiSy
  • 1,508
  • 9
  • 17