Filter file in using multer by file type

2019-08-27 23:19发布

问题:

I use multer module in nodejs to upload some images (only tiff and jpg format). I want filter and storage only tiff and jpg images.

For now I do this:

var upload = multer({
     storage: storage,
     fileFilter: function(req, file, cb){
          //---------------------------
          //CHECK IF THE FILE IS IN A CORRECT FORMAT
          //------------------------

          if((file.mimetype == "image/jpeg" || file.mimetype == "image/jpg" || file.mimetype == "image/tiff")){
                //correct format
                return cb(null, true);
           } else{ 
                //wrong format
                return cb(null, false);
           }
}

Using this code the problem is that multer checks the file extension and not the real type of file that depend of his encode. I've seen for example that exist some module that check the real type of a file i.e. this (I've only search it on google and I don't tested it) but I can't use this module in filefilter param because in scope I have only meta data of uploaded file but not the file content.

回答1:

You can use mmmagic to determine the real content type. It does data inspection instead of relying only on the file extensions for determining the content type.

An async libmagic binding for node.js for detecting content types by data inspection.

You need to store the file on the disk for mmmagic to inspect the content.

'use strict';

let multer = require('multer');
let fs = require('fs-extra');

let UPLOAD_LOCATION = path.join(__dirname, 'uploads');
fs.mkdirsSync(UPLOAD_LOCATION);

let upload = multer({
  storage: multer.diskStorage({
    destination: (req, file, callback) => {
      callback(null, UPLOAD_LOCATION);
    },
    filename: (req, file, callback) => {
      //originalname is the uploaded file's name with extn
      console.log(file.originalname);
      callback(null, file.originalname);
    }
  }),
  fileFilter: function fileFilter(req, file, cb) {

    let mmm = require('mmmagic'),
      Magic = mmm.Magic;

    let magic = new Magic(mmm.MAGIC_MIME_TYPE);
    let fileNameWithLocation = path.join(UPLOAD_LOCATION, file.originalname);

    magic.detectFile(fileNameWithLocation, function (err, mimeType) {
        if (err) {
          cb(err)
        }

        const ALLOWED_TYPES = [
          'image/jpeg',
          'image/jpg',
          'image/tiff'
        ];

        console.log(`mimeType => ${mimeType}`);
        cb(null, ALLOWED_TYPES.includes(mimeType));

      }
    );
  }
});