DEV Community

Narongdej Sarnsuwan
Narongdej Sarnsuwan

Posted on • Originally published at narongdej.dev on

Create image upload function in Google Firebase

I want to start a new hobby, where I post the solution to something I can’t find 2-3 google away. If I can’t Google and find my solution in one-shot. I’ll write a short tutorial about it. So here comes the first in this blog.

If you want to create an upload image endpoint inside Google Firebase (Cloud functions), then here is one way you can do it.

import * as functions from 'firebase-functions';
import * as Busboy from 'busboy';
import { tmpdir } from 'os';
import { join } from 'path';
import { createWriteStream, unlinkSync } from 'fs';
import * as FileType from 'file-type';
import * as admin from 'firebase-admin';

admin.initializeApp(); // It will automatically authenticate

export const uploadImage = functions.https.onRequest(async (request, response) => {
  const busboy = new Busboy({
    headers: request.headers,
    limits: {
      fileSize: 2 * 1024 * 1024, // max image size to 1 MB
      files: 1 // Limit to one file upload
    }
  });

  let filepath: string = "";
  const _tmpdir = tmpdir();

  busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
    filepath = join(_tmpdir, filename);
    const writeStream = createWriteStream(filepath);
    file.pipe(writeStream);
  });

  busboy.on('finish', async () => {
    const fileType = await FileType.fromFile(filepath);
    console.log(fileType);
    if(!fileType || !(fileType.mime === "image/jpeg" || fileType.mime === "image/png")) {
      unlinkSync(filepath);
      response.status(500).send({
        'error': 'Invalid file',
        'code': 'invalid_upload_file'
      });
      return;
    }

  await admin.storage().bucket().upload(filepath, {
    // Support for HTTP requests made with `Accept-Encoding: gzip`
    gzip: true,
    metadata: {
      // Enable long-lived HTTP caching headers
      // Use only if the contents of the file will never change
      // (If the contents will change, use cacheControl: 'no-cache')
      cacheControl: 'public, max-age=31536000',
    },
  });

    response.send({
      'status': 'Upload successful'
    });
  busboy.end(request.rawBody);
});
Enter fullscreen mode Exit fullscreen mode

I’m new to Google Firebase and Cloud functions, so this might not be the best way to do it, but it works

So what we did was

  1. Process the form data using busboy
  2. Store the image in a temp directory
  3. Upload the image using firebase-admin storage module

But what about multiple files upload at once?

You can modify this line

    limits: {
      ...
      files: 50 // <--- or remove it to allow infinity
    }
Enter fullscreen mode Exit fullscreen mode

and instead of replacing filepath you create an array of file paths instead. After that, process the filepaths array accordingly in

 busboy.on('finish', async () => {
   ...process the array
 });
Enter fullscreen mode Exit fullscreen mode

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay