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