Handle Image Uploads in Memory with Express.js

Building a feature-rich web application often requires simple yet effective solutions. One such example is managing uploaded images in memory, specifically camera screenshots. Here, I’ll walk you through how to create an Express.js endpoint that stores and retrieves screenshots from memory. This setup is ideal when you want lightweight, temporary storage for uploaded files without persisting them on disk.

Thank me by sharing on Twitter 🙏

Setting Up the Endpoint for Uploads

To handle file uploads in Express, I rely on the multer library. Multer makes it incredibly easy to manage file uploads in a structured way. For our use case, I’ll configure it to store files directly in memory. This keeps things fast and simple.

Here’s how the endpoint looks in TypeScript:

TypeScript
import express from 'express';
import multer from 'multer';

const app = express();
const port = 3000;

// Configure Multer to use memory storage
const storage = multer.memoryStorage();
const upload = multer({ storage });

// In-memory storage for screenshots
let screenshotBuffer: Buffer | null = null;

// POST endpoint to upload a screenshot
app.post('/upload', upload.single('screenshot'), (req, res) => {
    if (!req.file) {
        res.status(400).send('No file uploaded.');
        return;
    }

    // Store the screenshot in memory
    screenshotBuffer = req.file.buffer;
    res.send('Screenshot uploaded successfully.');
});

app.listen(port, () => {
    console.log(`Server running on http://localhost:${port}`);
});

Breaking Down the Code

  1. Memory Storage with Multer:
    Using multer.memoryStorage() ensures that files are stored temporarily in memory as buffers. This is perfect for cases where you don’t need permanent storage.
  2. Single File Upload:
    The upload.single('screenshot') middleware processes one file at a time. It expects the form field carrying the file to be named screenshot.
  3. Handling Errors:
    If no file is uploaded, I return a 400 Bad Request response. This ensures the client knows something went wrong.

Retrieving the Uploaded Screenshot

Once an image is uploaded, I want a way to retrieve it. This is where the GET endpoint comes into play. It serves the screenshot stored in memory if one exists.

Here’s the code for the retrieval endpoint:

TypeScript
// GET endpoint to retrieve the stored screenshot
app.get('/screenshot', (req, res) => {
    if (!screenshotBuffer) {
        res.status(404).send('No screenshot available.');
        return;
    }

    // Respond with the screenshot buffer
    res.set('Content-Type', 'image/png');
    res.send(screenshotBuffer);
});

How It Works

  1. Buffer Validation:
    Before sending the file, I check whether a screenshot exists in memory. If the buffer is empty, a 404 Not Found response is returned.
  2. Serving the File:
    The Content-Type header ensures that the response is treated as a PNG image. This can be modified to other formats if needed.

Testing the Endpoints

With the server running, I typically use tools like Postman to test both endpoints. Here’s how I do it:

  • Uploading a Screenshot:
    Send a POST request to /upload with a file in the screenshot form field. The response confirms whether the upload was successful.
  • Retrieving the Screenshot:
    Send a GET request to /screenshot. If an image has been uploaded, the server responds with the image data. Otherwise, you get a 404.

Key Features of This Approach

One thing I appreciate about this setup is its simplicity. Since the screenshot is stored in memory, there’s no need to manage file paths or clean up unused files. It’s a lightweight solution that works well for prototypes or temporary file handling.

That said, storing files in memory has its limitations. Memory usage increases with larger files, and the data is lost when the server restarts. If you need persistent storage or plan to handle large files, consider integrating a more robust solution like a cloud storage service.

Conclusion

Creating an Express.js endpoint for handling screenshots is a straightforward yet powerful feature to include in your application. By using multer and memory storage, you can quickly set up a temporary and efficient file handling system. Whether you’re working on a quick prototype or a project where simplicity is key, this approach gets the job done with minimal effort and maximum clarity.

Share this:

Leave a Reply