This app is a simple web application that provides file upload functionality to a Google Cloud Storage bucket. It uses the Express framework to define API endpoints for uploading, deleting, and checking files in the bucket. Multer is used for processing file uploads, and the @google-cloud/storage package is used for communicating with the Google Cloud Storage API. The app uses the cors package to enable CORS (Cross-Origin Resource Sharing) for all routes.
Prerequisites
Before we start building the app, make sure that you have the following installed:
Node.js and NPM (Node Package Manager) installed on your system
A Google Cloud Storage bucket set up
You will also need to have a basic understanding of Node.js and Express.
Setting up the project
To get started, create a new directory for your project and navigate to it in the terminal. Then run the following command to create a new Node.js project:
bash
npm init -y
This will create a new package.json file in the project directory.
Next, install the following packages:
express
@google-cloud/storage
multer
dotenv
cors
You can install these packages using NPM with the following command:
bash
npm install express @google-cloud/storage multer dotenv cors
We will be using environment variables to store sensitive information such as our Google Cloud Storage credentials. Create a new file in your project directory called .env and add the following variables:
Replace the placeholders with your own values. You can find your project ID, private key ID, private key, client email, and client ID in the JSON file that you downloaded when you created your Google Cloud Storage service account. The client X.509 certificate URL can be found in the service account details. The bucket name is the name of the bucket that you created in Google Cloud Storage. Finally, the port number is the port that the app will listen on.
Creating the app
Now that you have the necessary packages installed, create a new file named app.js in your project directory, and paste the following code into it:
javascript
// Import required modulesconst express = require("express");
const multer = require("multer");
const { Storage } = require("@google-cloud/storage");
require("dotenv").config();
const cors = require("cors");
//CORS is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served. In other words, it allows you to make requests to a server from a different domain. This is useful for web applications that are hosted on different domains, but need to communicate with each other. For example, if you have a web app hosted on a domain like example.com, and you want to make requests to a server hosted on a different domain like api.example.com, you will need to enable CORS for the API server.// Create a new Express appconst app = express();
// Enable CORS (Cross-Origin Resource Sharing) for all routes
app.use(cors());
// Create a new Storage instance using the credentials from the environment variablesconst storage = newStorage({
projectId: process.env.GOOGLE_CLOUD_PROJECT_ID,
credentials: {
type: "service_account",
project_id: process.env.GOOGLE_CLOUD_PROJECT_ID,
private_key_id: process.env.GOOGLE_CLOUD_PRIVATE_KEY_ID,
private_key: process.env.GOOGLE_CLOUD_PRIVATE_KEY,
client_email: process.env.GOOGLE_CLIENT_EMAIL,
client_id: process.env.GOOGLE_CLIENT_ID,
auth_uri: "https://accounts.google.com/o/oauth2/auth",
token_uri: "https://oauth2.googleapis.com/token",
auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
client_x509_cert_url: process.env.GOOGLE_CLIENT_X509_CERT_URL,
},
});
// Define a route to handle GET requests to the root URL
app.get("/", (req, res) => {
// Send a response with a dynamic message including an environment variable
res.send(`Hello, ${process.env.SOME_VAR}!`);
});
// Get the bucket object using the environment variableconst bucket = storage.bucket(process.env.GOOGLE_CLOUD_STORAGE_BUCKET);
// Create a new multer instance to handle file uploadsconst upload = multer({
// Use in-memory storage for uploaded filesstorage: multer.memoryStorage(),
// Limit the file size to 500MBlimits: {
fileSize: 500 * 1024 * 1024,
},
});
// Define a route to check if a file exists in the bucket
app.get("/check", async (req, res, next) => {
try {
// Get the filename from the query stringconst filename = req.query.filename;
// If the filename is not provided, return an error responseif (!filename) {
return res.status(400).send("Filename parameter is missing.");
}
// Get a reference to the file in the bucketconst file = bucket.file(filename);
// Check if the file exists in the bucketconst [exists] = await file.exists();
// Send a response with the result of the existence check
res.status(200).send({ exists });
} catch (err) {
// Pass any errors to the next middlewarenext(err);
}
});
// Define a route to handle file uploads
app.post("/upload", upload.single("file"), async (req, res, next) => {
try {
// If no file was uploaded, return an error responseif (!req.file) {
return res.status(400).send("No file uploaded.");
}
// Create a reference to the file in the bucket with the same name as the uploaded fileconst blob = bucket.file(req.file.originalname);
// Create a write stream for the file in the bucketconst blobStream = blob.createWriteStream({
resumable: false,
});
// Handle any errors that occur while writing the file to the bucket
blobStream.on("error", (err) => {
next(err);
});
// Handle the completion of the file upload
blobStream.on("finish", async () => {
const publicUrl = `https://storage.googleapis.com/${bucket.name}/${blob.name}`;
res.status(200).send(`File uploaded to: ${publicUrl}`);
});
// Get the public URL of the uploaded
blobStream.end(req.file.buffer);
} catch (err) {
next(err);
}
});
// Define a route to handle file deletions
app.delete("/delete", async (req, res, next) => {
try {
const filename = req.query.filename;
// If the filename is not provided, return an error responseif (!filename) {
return res.status(400).send("Filename parameter is missing.");
}
// Get a reference to the file in the bucketconst file = bucket.file(filename);
// Delete the file from the bucketawait file.delete();
// Send a response with a success message
res.status(200).send({ message: "File deleted successfully." });
} catch (err) {
next(err);
}
});
// Define a route to handle file downloadsconstPORT = process.env.PORT || 8080;
// Start the server
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}.`);
});