Creating an API with Express for Image Uploads to Google Drive

The other day, I was exploring alternatives for handling file uploads in web applications. I came across FTP servers, Multer, MongoDB, and storage services. I found a simple and versatile alternative that is also accessible (free). Of course, this solution is not recommended for more robust or large-scale applications. It is an ideal approach for POCs or small sites that need a quick and efficient solution for image file management.

So, I'm sharing an alternative solution for image file storage using the Google Drive API. Let's create an API using Express and the Multer library to upload images directly to Google Drive.

Step-by-Step Guide:

  1. Project Setup

  • Initialize a new Node.js project and install the necessary dependencies:

mkdir upload-api
cd upload-api
npm init -y
npm install express multer googleapis        

2. Creating Google Drive Credentials

  • Create a new project.
  • Enable the Google Drive API for the project.
  • Create credentials of the "Service Account" type and download the JSON file containing the credentials.
  • Share a folder on Google Drive with the service account email.

3. Express Server Setup

  • Create an index.js file to set up the Express server:

const express = require("express");
const app = express();
const uploadRouter = require("./routes/upload");

app.use(express.json());
app.use("/api", uploadRouter);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});        

4. Creating the Upload Route

  • Create the necessary folder and files structure:

mkdir routes modules
touch routes/upload.js modules/uploadService.js config.js        

  • Implement the upload route in routes/upload.js:

const express = require("express");
const router = express.Router();
const multer = require('multer');
const UploadService = require("../modules/uploadService");
const storage = multer.memoryStorage();
const uploadMiddleware = multer({ storage: storage });

router.post('/pictures/:id/upload', uploadMiddleware.single('file'), async (req, res) => {
  const file = req.file;
  const { id } = req.params;

  try {
    const result = await UploadService.config().uploadFile(id, file);
    res.status(200).json({url: result});
  } catch (error) {
    console.error(error);
    res.status(500).json({ success: false, message: error.message });
  }
});

module.exports = router;        

5. Implementing the Upload Service

  • Set up the upload service in modules/uploadService.js:

const { google } = require('googleapis');
const { Readable } = require('stream');
const config = require("../config");

class UploadService {
  static config() {
    return new UploadService();
  }

  async uploadFile(id, file) {
    const folderId = config.folderId;
    const client_email = config.client_email;
    const private_key = config.private_key;
    const { buffer } = file;
    const originalname = file.originalname;
    const transformName = `${id}-${Date.now()}-${originalname}`;

    try {
      const auth = new google.auth.GoogleAuth({
        credentials: {
          private_key,
          client_email,
        },
        scopes: ['https://www.googleapis.com/auth/drive']
      });

      const driveService = google.drive({
        version: 'v3',
        auth
      });

      const fileMetaData = {
        name: transformName,
        parents: [folderId]
      };

      const media = {
        mimeType: file.mimetype,
        body: Readable.from(buffer)
      };

      const response = await driveService.files.create({
        resource: fileMetaData,
        media,
        fields: 'id'
      });

      // Note: the default URL returned by Google Drive does not load in an HTML <img> tag.
      // Therefore, we use an alternative URL format by passing the image ID.
      return `https://lh3.googleusercontent.com/d/${response.data.id}`;
    } catch (error) {
      console.error("Error uploading the image:", error);
      throw new Error("Upload failed");
    }
  }
}

module.exports = UploadService;        

6. Configuring Credentials and Environment Variables

  • Set the configurations in config.js:

module.exports = {
  folderId: 'PASTE_YOUR_FOLDER_ID_HERE',
  client_email: 'YOUR_SERVICE_ACCOUNT_EMAIL',
  private_key: 'YOUR_PRIVATE_KEY'.replace(/\\n/g, '\n')
};        

  • Replace PASTE_YOUR_FOLDER_ID_HERE, YOUR_SERVICE_ACCOUNT_EMAIL, and YOUR_PRIVATE_KEY with the corresponding values from your Google credentials JSON file.

7. Running the Server

  • Start the server:

node index.js        

8. Testing the API

  • Use tools like Postman or cURL to test the image upload route:

curl -X POST https://localhost:3000/api/pictures/123/upload -F file=@path/to/your/image.jpg        

Remember to add the email created in the console to the permissions of your Google Drive folder, and make sure to grant edit access.

This solution provides a quick and effective way to manage image uploads to Google Drive, ideal for prototypes and small projects. Feel free to share your experiences and improvements in the comments!


Juan Mantilla

English | Spanish | French| Interpreter | | Bilingual |

8 个月

Thanks for sharing

Juan Mantilla

English | Spanish | French| Interpreter | | Bilingual |

8 个月

Very helpful!

要查看或添加评论,请登录

Joir Neto的更多文章

社区洞察

其他会员也浏览了