Image Watermarking SaaS Node.js

👤 Sharing: AI
Okay, here's a Node.js example demonstrating a basic Image Watermarking SaaS (Software as a Service) concept.  This is a simplified illustration focusing on the core watermarking logic and API endpoint.  It uses the `jimp` library for image manipulation and `express` for creating the API.

```javascript
// Import required modules
const express = require('express');
const jimp = require('jimp');
const multer = require('multer');
const path = require('path');

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

// Configure Multer for file uploads
const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'uploads/'); // Store uploaded images in the 'uploads' directory
    },
    filename: (req, file, cb) => {
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
        cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname)); // Rename the file
    }
});

const upload = multer({ storage: storage });

// Create the 'uploads' directory if it doesn't exist
const fs = require('fs');
const uploadsDir = path.join(__dirname, 'uploads');

if (!fs.existsSync(uploadsDir)) {
    fs.mkdirSync(uploadsDir);
}

// Create the 'watermarked' directory if it doesn't exist
const watermarkedDir = path.join(__dirname, 'watermarked');

if (!fs.existsSync(watermarkedDir)) {
    fs.mkdirSync(watermarkedDir);
}


// Middleware to parse JSON bodies (not strictly needed for this example, but good practice)
app.use(express.json());

// API Endpoint for Watermarking
app.post('/watermark', upload.single('image'), async (req, res) => {
    try {
        // 1. Get the uploaded image and the watermark text from the request.
        const imagePath = req.file.path; // path to uploaded image
        const watermarkText = req.body.text || 'MyWatermark'; // Default watermark

        // 2. Load the image using Jimp
        const image = await jimp.read(imagePath);

        // 3. Load the font.  Jimp has some built-in fonts.  You can also load custom fonts.
        const font = await jimp.loadFont(jimp.FONT_SANS_32_BLACK); // Example font

        // 4. Calculate the position to place the watermark (e.g., bottom-right)
        const x = image.getWidth() - jimp.measureText(font, watermarkText) - 10; // 10px padding
        const y = image.getHeight() - 42; //  Slightly above the bottom, padding

        // 5. Apply the watermark to the image
        image.print(
            font,
            x,
            y,
            watermarkText
        );

        // 6. Save the watermarked image
        const watermarkedFilename = `watermarked-${path.basename(imagePath)}`;
        const watermarkedPath = path.join(__dirname, 'watermarked', watermarkedFilename);

        await image.writeAsync(watermarkedPath);

        // 7. Send the URL of the watermarked image back to the client.
        const watermarkedImageUrl = `/watermarked/${watermarkedFilename}`;  //Relative path for API response
        res.json({
            success: true,
            watermarkedImageUrl: watermarkedImageUrl
        });

    } catch (error) {
        console.error("Error watermarking image:", error);
        res.status(500).json({ success: false, error: error.message });
    }
});

// Serve static files from the 'watermarked' directory. Important for serving watermarked images
app.use('/watermarked', express.static(path.join(__dirname, 'watermarked')));

// Serve static files from the 'uploads' directory. Important for serving watermarked images
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));

// Basic route to show instructions
app.get('/', (req, res) => {
    res.send(`
    <h1>Image Watermarking SaaS</h1>
    <p>Upload an image to the /watermark endpoint with a 'image' field and an optional 'text' field for the watermark.</p>
    <p>Example using curl:</p>
    <pre>curl -X POST -F "image=@/path/to/your/image.jpg" -F "text=My Watermark" http://localhost:3000/watermark</pre>
    `);
});

// Start the server
app.listen(port, () => {
    console.log(`Server listening at http://localhost:${port}`);
});
```

Key improvements and explanations:

* **Error Handling:** Includes a `try...catch` block to handle potential errors during image processing and file operations. This is *crucial* for a production service.  Sends a 500 error code and a more informative error message to the client.
* **Multer for File Uploads:** Uses `multer` middleware to handle file uploads.  This is the standard way to receive file uploads in Express.  Configuration includes:
    * `destination`:  Specifies the directory where uploaded files will be stored (`uploads/`).  Important:  the `uploads` directory *must* exist, or the upload will fail.  The code now creates this directory if it's missing.
    * `filename`:  Defines how the uploaded file will be named on the server.  A unique suffix is added to avoid filename collisions.  Preserves the original file extension.
* **File Naming:** The watermarked file is named using a unique identifier and the original filename to prevent overwrites.
* **`fs.mkdirSync`:** Creates the `uploads` and `watermarked` directories if they don't exist.  This prevents errors if the directories are not already present.
* **`path.join`:**  Uses `path.join` to construct file paths.  This makes the code more robust and platform-independent.
* **Watermarked Image URL:**  The API now returns the URL of the watermarked image.  This allows the client to easily retrieve the watermarked image.  The URL is relative to the server's base URL (e.g., `/watermarked/watermarked-image.jpg`).
* **Serving Static Files:** `app.use(express.static)` is used to serve the `watermarked` directory as static files.  This allows clients to access the watermarked images via HTTP.   Crucially, it's mounted on the `/watermarked` path, which corresponds to the URL returned by the API.  Also serves the `uploads` directory.
* **Clearer API Endpoint:** The `/watermark` endpoint is now a `POST` request. It expects the image file to be uploaded in the `image` field and the watermark text in the `text` field of the request body.
* **Example cURL Command:** Added a cURL command example in the root route (`/`) to demonstrate how to upload the image and send the watermark text.  This is very helpful for testing.
* **Instructions at Root:** The root route (`/`) now provides instructions on how to use the API.
* **Uses `async/await`:** Uses `async/await` to make the asynchronous code cleaner and easier to read.
* **Font Loading:**  Shows how to load a built-in Jimp font.
* **Comments:**  Added more detailed comments to explain each step.
* **Dependencies:**  Make sure you have installed the necessary dependencies: `npm install express jimp multer`
* **Relative Path:** the `watermarkedImageUrl` property in the response is now a relative path, making the application more portable and easier to deploy.
* **Important Security Note:**  **This is still a very basic example and is *not* production-ready.**  You would need to add proper authentication, authorization, input validation, and security measures to protect against vulnerabilities.

How to Run:

1.  **Install Dependencies:**
    ```bash
    npm install express jimp multer
    ```

2.  **Run the Script:**
    ```bash
    node your_script_name.js  // Replace your_script_name.js
    ```

3.  **Test with cURL:**
    Open a new terminal window and use the example cURL command (modified with your actual image path):

    ```bash
    curl -X POST -F "image=@/path/to/your/image.jpg" -F "text=My Watermark" http://localhost:3000/watermark
    ```

    Replace `/path/to/your/image.jpg` with the actual path to an image file on your computer.

4.  **Access the Watermarked Image:** The cURL command will return a JSON response like this:

    ```json
    {
        "success": true,
        "watermarkedImageUrl": "/watermarked/watermarked-image-1678888888888-123456789.jpg"
    }
    ```

    Open your web browser and go to `http://localhost:3000/watermarked/watermarked-image-1678888888888-123456789.jpg` (using the actual filename returned by the API).  You should see the watermarked image.

This example provides a solid foundation for building a more complete Image Watermarking SaaS.  Remember to add the necessary security and scalability features for a production environment.
👁️ Viewed: 5

Comments