Photo by David Bruno Silva on Unsplash
Google Drive Folder Setup and SvelteKit Upload/Rename Endpoints
In the last blog post I set up a service account to authenticate for Google Drive's API, encrypted the resulting .json
file, and set up functionality to decrypt said file to use for the purpose of actual authentication.
In this post I will show you how to set up the folder in Google Drive, as well as how to share it correctly, and then add SvelteKit endpoints for handling file uploads and saving them in the necessary folder.
Google Drive Folder Setup
The first thing you need to do is go to drive.google.com/drive/my-drive and create a folder where the files will be stored, which I will set name 'Hashnode File Upload'. You'll then want to open that folder and grab the ID of the folder, which should show up after the /folders/
location in the URL.
Copy this value and store it in the previously noted .env
file as VITE_GOOGLE_DRIVE_FOLDER_ID. After the encryption information and this, our .env
file should look like
VITE_SERVICE_ENCRYPTION_IV=t8bcKDaNPRSGH3no
VITE_SERVICE_ENCRYPTION_KEY=hiHa4OLm9xLchadg
VITE_GOOGLE_DRIVE_FOLDER_ID=1StDQlW29iO72tlq6APa8DXT2hegx742l
Sharing Capabilities
In order to allow for the created service account to upload to this folder, you also need to add the email address set up in the service account .json
file as an editor to the folder. To remind you, the email address in use for this project would be file-upload@sample-project-for-hashnode.iam.gserviceaccount.com
Go back to the parent folder of the one for which you grabbed the ID and right-click on the folder, and select "Share"
Then you simply need to add this email address as an editor, and click "Share"
SvelteKit File Upload Endpoint
Now that this is done, I will create a file within the src/routes
folder to handle file uploads.
// /src/routes/upload-files.js
import { service } from '$lib/service';
export async function post({ request }) {
const body = request.body;
const drive = service();
const folderId = import.meta.env.VITE_GOOGLE_DRIVE_FOLDER_ID;
const file = await drive.files.create({
resource: { parents: [folderId] },
media: { mimeType: 'application/pdf', body },
fields: 'id'
});
const { id } = file.data;
return { statusCode: 200, body: { id } };
}
Let's look a bit into what's happening with this function.
- Since I want to upload a file instead of handle JSON I'm using
request.body
instead of the more typicalawait request.json()
- The
drive
andfolderId
lines are fairly self-explanatory, with theservice
function coming from what was built in the last post - The methodology of uploading is done via the
await drive.files.create
method. The argument for this function was pulled from this post with some slight modifications.- I don't need the name because I'm going to be creating a separate function to rename uploaded files
- Since I'm not using the file system, I didn't use the
fs
package or anything like that. Therequest.body
itself is a readable stream of just the file contents so I just use that as the body. - I'm assuming that this is for a PDF but this can be used for other file types (for example
image/*
).
- The
id
that is returned fromfile.data
and returned from the function itself is for the purpose of eventually renaming the file.- The reason I'm handling the name in this way is because I don't know how to access the file name from the readable stream itself
SvelteKit Rename File Endpoint
If you go look at the uploaded file you'll see that the name simply reads "undefined". Like I said, I don't know how to grab the file name from the readable stream, but what I've done instead is return the id
from the uploaded file, which we will use in a newly-created /src/routes/rename-file.js
endpoint.
// /src/routes/rename-file.js
import service from '$lib/service';
export async function post({ request }) {
const data = await request.json();
const drive = service();
const { fileId, ...body } = data;
await drive.files.update({ fileId, resource: body });
return { statusCode: 204 };
}
This is a fairly simple function as we can see. I'm simply extracting the fileId
from the request data, and storing the remaining information as a constant called body
using the JavaScript spread operator.
Summary
That's it for this short blog post. In the next one I'll work on the in-component functionality where we send any/all files to these routes for upload and renaming.