You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Node.js+Express中使用Multer上传前验证图片宽高

Validate Image Dimensions Before Upload with Multer (Node.js/Express)

Got it, I totally get where you're coming from—having that pre-upload validation like you did in CodeIgniter makes way more sense than cleaning up files after they're already on your server. The key here is to avoid writing the file to disk until we've confirmed its dimensions, which we can do using Multer's memory storage combined with an efficient image processing library like sharp.

Here's a step-by-step solution tailored to your needs:

1. Install Required Packages

First, grab the libraries we'll use for upload handling and image validation:

npm install multer sharp

2. Set Up Custom File Filter with Dimension Checks

We'll use Multer's memoryStorage to temporarily hold the file in memory (instead of writing it to disk immediately), then use sharp to read its dimensions before allowing the upload to proceed.

const multer = require('multer');
const sharp = require('sharp');
const path = require('path');
const fs = require('fs/promises');

// Create uploads directory if it doesn't exist
const ensureUploadsDir = async () => {
  const uploadsPath = path.join(__dirname, 'uploads');
  try {
    await fs.access(uploadsPath);
  } catch {
    await fs.mkdir(uploadsPath);
  }
};
ensureUploadsDir();

// Custom filter to validate image dimensions pre-upload
const validateImageSize = async (req, file, cb) => {
  // First, verify the file is an image
  if (!file.mimetype.startsWith('image/')) {
    return cb(new Error('Only image files are allowed!'), false);
  }

  try {
    // Read image metadata (including dimensions) from the in-memory buffer
    const metadata = await sharp(file.buffer).metadata();
    const { width, height } = metadata;

    // Define your required dimensions (70px × 40px here)
    const requiredWidth = 70;
    const requiredHeight = 40;

    if (width !== requiredWidth || height !== requiredHeight) {
      return cb(
        new Error(`Image must be exactly ${requiredWidth}px × ${requiredHeight}px. Received ${width}px × ${height}px`),
        false
      );
    }

    // Dimensions are valid—allow the upload
    cb(null, true);
  } catch (err) {
    cb(new Error('Failed to validate image dimensions. Ensure the file is a valid image.'), false);
  }
};

// Configure Multer with memory storage and our custom filter
const upload = multer({
  storage: multer.memoryStorage(), // Temporarily store file in memory
  fileFilter: validateImageSize,
  limits: {
    fileSize: 1 * 1024 * 1024 // Limit file size to 1MB to avoid memory overload
  }
});

3. Create the Upload Route

Once validation passes, we'll write the in-memory file to your server's disk:

const express = require('express');
const app = express();

app.post('/upload-image', upload.single('image'), async (req, res) => {
  try {
    // Save the validated image from memory to disk
    const savePath = path.join(__dirname, 'uploads', req.file.originalname);
    await sharp(req.file.buffer).toFile(savePath);

    res.status(200).send('Image uploaded successfully!');
  } catch (err) {
    res.status(500).send(`Failed to save image: ${err.message}`);
  }
});

// Error handling middleware for upload/validation errors
app.use((err, req, res, next) => {
  if (err instanceof multer.MulterError) {
    res.status(400).send(`Upload error: ${err.message}`);
  } else if (err) {
    res.status(400).send(err.message);
  } else {
    next();
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

Key Details to Note

  • Memory storage benefit: This ensures the file never touches your disk unless it passes validation, matching your CodeIgniter workflow. If validation fails, the in-memory buffer is automatically garbage-collected.
  • Memory limits: Always set a fileSize cap to prevent large images from eating up your server's memory—adjust the value based on your use case.
  • Alternative with Jimp: If you prefer a simpler API, replace sharp with jimp—the core logic stays the same; you'll just swap the metadata reading step with Jimp's read() method.

内容的提问来源于stack exchange,提问作者Gaurav Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:38:53