Home > Back-end >  Downloading Sqlite backup file from google drive ends up with a corrupt file nodejs Vue
Downloading Sqlite backup file from google drive ends up with a corrupt file nodejs Vue

Time:11-09

I am working on a backup system with Google Drive v3 REST API. I upload a sqlite backup file to a folder on Google Drive. That works. I am able to upload and list the files in the folder.

So now I am working on restoring that file in my application. But when I download the file and write the response stream I end up with a corrupted db file. When I open it up in notepad I see that any special characters such as ^ etc are all squares and the file is like 2 mb bigger than what was uploaded.

I have been at this for two days now and cannot figure out why the file is not writing 1:1 copy of what is downloaded

this is my current code for the download ..

async restoreGoogleDriveDatabase(fileId){
        const url = encodeURI(`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`);
        const options = {
            method: 'GET',
            headers: {
                'Authorization': 'Bearer '   this.getToken()
            },
        }
       await fetch(url, options).then(async response => response.text())
           .then(arrayBuffer => {

const path = require('path').join(window.process.env.ProgramData, 'Home Inventory');
               fs.writeFile(`${path}\\HomeInventory1.db`, arrayBuffer, function () {
                   console.warn('file created');
               });
           });
    },

Looking for any kind of help that would get me back on the right track.

CodePudding user response:

The issue seems to be with character encoding

The simplest fix is to fetch the result as an arrayBuffer, and write out the arrayBuffer using "binary" encoding

Like so

const fs = require('node:fs/promises');

async restoreGoogleDriveDatabase(fileId) {
    const url = encodeURI(`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`);
    const options = {
        method: 'GET',
        headers: {
            'Authorization': 'Bearer '   this.getToken()
        },
    }
    try {
        const response = await fetch(url, options);
        const arrayBuffer = await response.arrayBuffer();
        const path = require('path').join(window.process.env.ProgramData, 'Home Inventory');
        await fs.writeFile(`${path}/HomeInventory1.db`, Buffer.from(arrayBuffer, "binary"));
        console.warn('file created');
    } catch (err) {
        console.error(err);
    }
},

The code above uses async/await correctly, and also uses fs/promises instead of fs, since already using async/await it makes sense to use the Promise version of fs methods

The important changes are

response.arrayBuffer()

To get the response as an arrayBuffer

and in fs.writeFile use

Buffer.from(arrayBuffer, "binary")

To write the data "as-is" to the file

  • Related