Building a Node app that uploads data to Google Drive

Making use of Koa.js to upload JSON data to Google Drive

Eder Negrete
Apr 19, 2018 · 5 min read

The goal of this post is to make a Koa.js app that uploads a JSON file to our Google Drive, this is how we’re gonna achieve that:

We’ll send a POST request to /create with any JSON in the body and the app will create a JSON file and it will upload it to Google Drive, after that the file should be removed. Easy right?

These are the steps we’re gonna follow:

  • Create the basic structure
  • Configure the project
  • Create the server
  • Google Auth
  • Create the Koa App
  • Run the app

Create the basic structure

Create a folder with any name you want, this will be the root of our project, after that create this structure:

| Koa Tutorial
|__nodemon.json
|__files
|__src
|__app.js
|__google-auth.js
|__server.js

Configure the project

Inside the root folder make

npm init

and fill all the data in it, if you want to skip all that simply do

npm init --yes

Add the dependences, this is my package.json:

{
"name": "koa-app",
"version": "0.0.1",
"license": "MIT",
"main": "src/server.js",
"dependencies": {
"google-auth-library": "0.12.0",
"googleapis": "24.0.0",
"jsonwebtoken": "latest",
"koa": "latest",
"koa-body": "latest",
"koa-bodyparser": "4.2.0",
"koa-logger": "latest",
"koa-router": "latest"
},
"devDependencies": {
"nodemon": "latest"
},
"scripts": {
"dev": "DEBUG=* NODE_ENV=local nodemon --inspect --harmony src/server.js"
}
}

Install the dependences:

npm install

Let’s configure nodemon, go to the nodemon.json file

This is important, because we need to ignore the changes inside the /files folder so nodemon doesn’t restart the server each time a change happens there.

// nodemon.json
{
"ignore": ["files/*.json"]
}

Create the server

Go to the server.js file

// src/server.jsprocess.env.NODE_ENV = process.env.NODE_ENV || 'development';const app = require('./app');const config = {
port: process.env.PORT || 9000,
env: process.env.NODE_ENV,
};
app.listen(config.port, config.ip, () => {
console.log('Koa server listening on %d, in %s mode', config.port, config.env);
});
// Expose app
exports = module.exports = app;

Google Auth

First, we need to do the “Step 1: Turn on the Drive API” in this link:

Add this URI in the URI section 127.0.0.1:900/auth

We download the client_secret.json and we add it to our /src folder

I refactored the code that comes in the Google example from the link above, we download it from here: https://github.com/edernegrete/google-drive-auth-module-node/blob/master/auth.js

And we put it at src/google-auth.js

Create the Koa App

Finally, to the Koa app.

We need to create two endpoints

  • /auth (for the Google Auth)
  • /create (create a file with the provided JSON)

Go to the src/app.js

Let’s add the dependencies first:

//src/app.jsprocess.env.NODE_ENV = process.env.NODE_ENV || 'development';const Koa = require('koa');
const logger = require('koa-logger');
const router = require('koa-router')();
const bodyParser = require('koa-bodyparser');
const fs = require('fs');
const uploadFile = require('./google-auth.js');

Now let’s add the logger:

//src/app.jsapp.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});

Let’s create two functions

  • writeJSONFile
  • removeFile

The process should be this:

  1. Write the JSON file
  2. Upload the file
  3. Remove the file

All of those should wait for the one before to end. (async / await 🙈)

Let’s write the writeJSONFile function:

// src/app.jsconst writeJSONFile = (ctx, fileName) => new Promise(
(resolve, reject) => {
try {
const createStream = fs.createWriteStream(`./files/${fileName}.json`);
const writeStream = fs.createWriteStream(`./files/${fileName}.json`);
writeStream.write(JSON.stringify(ctx.request.body));
createStream.end();
writeStream.end();
resolve();
} catch (err)
{
reject(err);
}
});

Now the removeFile function:

// src/app.jsconst removeFile = fileName => new Promise((resolve, reject) => {
fs.unlink(`./files/${fileName}.json`, (err) => {
if (err) {
reject(err);
throw err;
}
resolve();
console.log('filePath was deleted');
});
});

Now let’s create the routes

/create

// src/app.jsrouter.post('/create', async (ctx, next) => {
if (!ctx.request.body) {
ctx.status = 400;
ctx.body = {
error: `expected an object in the body but got: ${ctx.request.body}`,
};
return;
}
const newName = `${new Date().getTime()}`;
await writeJSONFile(ctx, newName);
await uploadFile.upload(newName);
await removeFile(newName);
ctx.status = 200;
next();
});

/auth

// src/app.jsrouter.get('/auth', async (ctx) => {
ctx.body = {
message: ctx.request.query.code,
};
});

And at the end we need no use the routes and export our app

// src/app.jsapp.use(router.routes());
app.use(router.allowedMethods());
module.exports = app;

Let’s run the app.

Go to the terminal and run

npm run dev

You should see something like this:

Our app is at the 9000

Now to do the test we need to make a request, you can use Postman or any rest client

We need to do a POST to /create with any valid JSON in it

After that you should auth with Google, go to the console and you should see this:

Let’s access that link, and you will see something like this (depending if you have multiple Google Accounts)

After you select onau’ll see the token:

Copy and Paste it in the terminal and the process should begin, you should see something like this at the end:

And after that you can check your Google Drive and the file should be there:

You can check the full code here: https://github.com/edernegrete/koa-google-drive

I’d love to hear from you, you can reach me out on twitter: @edernegrete_ ❤️

JavaScript in Plain English

Learn the web's most important programming language.

Eder Negrete

Written by

Frontend Engineer at RunaHR

JavaScript in Plain English

Learn the web's most important programming language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade