In this tutorial, we'll walk through the process of creating a serverless API using Next.js that allows users to upload files directly to Google Drive. We'll use the Google Drive API for file storage and Next.js for the serverless API endpoints.
Prerequisites
Before getting started, make sure you have the following:
- - A Google Cloud Platform (GCP) project with the Google Drive API enabled.
- - API credentials in the form of a service account key (JSON file).
- - Node.js and npm installed on your development machine.
Setting Up the Project
- Initialize a Next.js Project:
npx create-next-app my-drive-api
cd my-drive-api
- Install Dependencies:
npm install googleapis multer stream
- Api Code
// pages/api/googleDrive.js
import { google } from "googleapis";
const stream = require("stream");
import multer from "multer";
const apikeys = require("./apikeys.json");
const SCOPE = ["https://www.googleapis.com/auth/drive"];
export const config = {
api: {
bodyParser: false,
},
};
// Function to authorize the Google Drive API
async function authorize() {
const jwtClient = new google.auth.JWT(
apikeys.client_email,
null,
apikeys.private_key,
SCOPE
);
await jwtClient.authorize();
return jwtClient;
}
// Multer storage configuration
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
// API endpoint handler
export default async function handler(req: any, res: any) {
if (req.method !== "POST") {
return res.status(405).end(); // Method Not Allowed
}
try {
await new Promise<void>((resolve, reject) => {
upload.single("image")(req as any, res as any, (err) => {
if (err) {
return reject(err); // Reject if multer encounters an error
}
resolve();
});
});
const uploadedFile = req.file;
if (!uploadedFile) {
return res.status(400).json({ error: "No file uploaded" });
}
const authClient = await authorize();
const result: any = await uploadFile(authClient, uploadedFile);
// Wait for a short delay (e.g., 2 seconds) before responding
await new Promise((resolve) => setTimeout(resolve, 2000));
const previewLink = `https://drive.google.com/uc?id=${result?.data?.id}`;
res.status(200).json({ previewLink, id: result?.data?.id });
} catch (error: any) {
console.error(error);
res.status(500).json({ error: error?.message ?? "Internal Server Error" });
}
}
// Function to upload a file to Google Drive
async function uploadFile(authClient: any, uploadedFile: any) {
return new Promise((resolve, reject) => {
const drive = google.drive({ version: "v3", auth: authClient });
const fileMetaData = {
name: uploadedFile.originalname,
parents: ["1rE3jBXCsPoABRPCyHhvHBqH9SxzzFzCm"],
};
drive.files.create(
{
resource: fileMetaData,
media: {
mimeType: uploadedFile.mimetype,
body: stream.PassThrough().end(uploadedFile.buffer),
},
fields: "id",
},
(error: any, file: any) => {
if (error) {
return reject(error); // Reject if there's an error during file creation
}
// Set permissions to make the file public
drive.permissions.create(
{
fileId: file.data.id,
requestBody: {
role: "reader",
type: "anyone",
},
},
(err: any) => {
if (err) {
console.error(err);
return reject(err); // Reject if there's an error setting permissions
}
resolve(file);
}
);
}
);
});
}
Top comments (0)