Managed to store my files in a folder but they store without the file extension.
Does any one know how would I store the file with file extension?
I have a workaround for the adding proper extension of files. If you use path
node module
var multer = require('multer');
var path = require('path')
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + path.extname(file.originalname)) //Appending extension
}
})
var upload = multer({ storage: storage });
From the docs: "Multer will not append any file extension for you, your function should return a filename complete with an file extension."
Here's how you can add the extension:
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '.jpg') //Appending .jpg
}
})
var upload = multer({ storage: storage });
I would recommend using the mimetype
property to determine the extension. For example:
filename: function (req, file, cb) {
console.log(file.mimetype); //Will return something like: image/jpeg
More info: https://github.com/expressjs/multer
I got file the extension from file.mimetype
.
I split the mimetype and get the file extension from it
Please try the below function.
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
let extArray = file.mimetype.split("/");
let extension = extArray[extArray.length - 1];
cb(null, file.fieldname + '-' + Date.now()+ '.' +extension)
}
})
const upload = multer({ storage: storage })
It can be done like this:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, config.DIR)
},
filename: function (req, file, cb) {
let ext = file.originalname.substring(file.originalname.lastIndexOf('.'), file.originalname.length);
cb(null, Date.now() + ext)
}
});
const upload = multer({
storage: storage
}).any();
import multer from 'multer';
import * as shortid from 'shortid';
import * as mime from 'mime-types';
const storage = multer.diskStorage({
destination: function (req,file,cb) {
cb(null, '/path/to/uploads/');
},
filename: function (req,file,cb) {
/* generates a "unique" name - not collision proof but unique enough for small sized applications */
let id = shortid.generate();
/* need to use the file's mimetype because the file name may not have an extension at all */
let ext = mime.extension(file.mimetype);
cb(null, `${id}.${ext}`);
}
});
EDIT
shortid has been deprecated you should use nanoid.
import multer from 'multer';
import * as nanoid from 'nanoid';
import * as mime from 'mime-types';
const storage = multer.diskStorage({
destination: function (req,file,cb) {
cb(null, '/path/to/uploads/');
},
filename: function (req,file,cb) {
/* generates a "unique" name - not collision proof but unique enough for small sized applications */
let id = nanoid();
/* need to use the file's mimetype because the file name may not have an extension at all */
let ext = mime.extension(file.mimetype);
cb(null, `${id}.${ext}`);
}
});
There may be some issues in the already answered codes.
upload.any()
usage. Its vulnerable to the attackersI have written the below codes for better security.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'temp/')
},
filename: function (req, file, cb) {
let ext = ''; // set default extension (if any)
if (file.originalname.split(".").length>1) // checking if there is an extension or not.
ext = file.originalname.substring(file.originalname.lastIndexOf('.'), file.originalname.length);
cb(null, Date.now() + ext)
}
})
var upload = multer({ storage: storage });
Using it for upload
// using only single file object name (HTML name attribute)
// May use upload.array(["file1","file2"]) for more than one
app.post('/file_upload', upload.single("file"), function (req,res) {
//console.log(req.body, 'Body');
console.log(req.file, 'file');
res.send("cool");
})
I used this little trick to get file extension, and as a workaround to circumvent issues that might occur when someone uploads a file with similar file name twice, or that exists in the server.
const path = require('path');
const crypto = require('crypto');
let upload = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.join(__dirname, '../uploads'))
},
filename: (req, file, cb) => {
// randomBytes function will generate a random name
let customFileName = crypto.randomBytes(18).toString('hex')
// get file extension from original file name
let fileExtension = path.extname(file.originalname).split('.')[1];
cb(null, customFileName + '.' + fileExtension)
}
})
})
const multer = require('multer'); const uuid = require('uuid/v1');
const MIME_TYPE_MAP = {
'image/png': 'png',
'image/jpeg': 'jpeg',
'image/jpg': 'jpg'
};
const fileUpload = multer({
limits: 500000,
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/images');
},
filename: (req, file, cb) => {
const ext = MIME_TYPE_MAP[file.mimetype];
cb(null, uuid() + '.' + ext);
}
}),
fileFilter: (req, file, cb) => {
const isValid = !!MIME_TYPE_MAP[file.mimetype];
let error = isValid ? null : new Error('Invalid mime type!');
cb(error, isValid);
}
});
module.exports = fileUpload;
The file extension can be dynamic. here is the solution
const path = require('path'); // path for cut the file extension
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads')
},
filename: function (req, file, cb) {
cb(null, 'upload_at_' + Date.now() + path.extname(file.originalname))
}
})
I use this method and it works.
I store the file in this format: FieldName+Date+Extension => Profile1621416613594.jpg
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req,file,cb){
cb(null, './uploads')
},
filename: function (req,file,cb){
cb(null,file.fieldname+'-'+Date.now()+'.'+file.mimetype.split('/').reverse()[0]);
},
});
var upload = multer({storage: storage});
let fileext = file.originalname.split('.').pop();
cb(null,'profile_' + Date.now() + file.originalname.substring(0, 10).split(' ').join('-') + '.' + fileext)
I am doing like this
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/img/')
},
filename: function (req, file, cb) {
let ext = file.originalname.substring(file.originalname.lastIndexOf('.'), file.originalname.length);
cb(null, Date.now() + ext);
}
})
var upload = multer({ storage: storage }).single('eventimage');
An object oriented way to store image with unique name
// image.service.ts
import { diskStorage, StorageEngine } from "multer";
class ImageStorageService {
storage: StorageEngine
constructor() {
const MIME_TYPE_MAP = {
'image/png': 'png',
'image/jpeg': 'jpg',
'image/jpg': 'jpg'
}
this.storage = diskStorage({
destination: (req, file, callback) => {
const isValid = MIME_TYPE_MAP[file.mimetype]
let error = new Error(`Invalid mime type`)
if (isValid)
error = null
//app.use(express.static(path.join(`${__dirname}/assets`)))
callback(error, 'assets/images')
},
filename: (req, file, callback) => {
let currentFileName: string = file.originalname.substr(0, file.originalname.lastIndexOf('.'))
const name = currentFileName.toLowerCase().split(' ').join('-')
const ext = MIME_TYPE_MAP[file.mimetype]
callback(null, `${name}-${Date.now()}.${ext}`)
}
})
}
}
export const ImageStorage = new ImageStorageService().storage
then in one of your routes
import { ImageStorage } from "./services/image-storage.service";
this.router.post('/signup', multer({ storage: ImageStorage }).single('image'), async (req, res, next) => {
let img_url: string
if (req.file) {
const url: string = `${req.protocol}:\/\/${req.get('host')}`
img_url = url + '/images/' + req.file.filename
//http://localhost:3000/images/penguins-1548339248380.jpg
}
})
I like to use the original filename for SEO purposes. This requires a bit more checking if the file with the same name already exists. Moreover, extension resolving is done in a few steps to provide maximum flexibility.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
// try to get extension from original file name
var lioDot = file.originalname.lastIndexOf('.');
if (lioDot !== -1) {
// I like to use original upload filename for SEO but first lets clean it
var newName = file.originalname.substring(0, lioDot).replace(/([^a-z0-9]+)/gi, '-');
var ext = file.originalname.substring(lioDot, file.originalname.length);
} else {
var newName = file.originalname.replace(/([^a-z0-9]+)/gi, '-');
// try to get extension from mime type string
var extArray = file.mimetype.split("/");
var ext = extArray[extArray.length - 1];
// mime type extension resolving by pure string extraction is not accurate for a lot of types
// https://www.freeformatter.com/mime-types-list.html
// it's usually fine for ext strings up to 4 characters, png, jpeg, gif, bmp, tiff ..
if (ext > 4) {
// other mime types you would like to support
var mimetypes = { 'vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx' };
if (mimetypes.hasOwnProperty(ext)) ext = mimetypes[ext];
}
}
var newFullName = newName + ext;
var i = 0;
// we need to check if the file with the same name already exists
// if it exists then we're adding something to make it unique
while (fs.existsSync(process.env.PWD + '/uploads/' + newFullName)) {
newFullName = newName + '-' + ++i + ext;
}
cb(null, newFullName);
}
})
const upload = multer({ storage: storage });
It can be done like this...simple to grasp
// validate uploaded files
const FILE_TYPE_MAP = {
// mime type
"image/png": "png",
"image/jpeg": "jpeg",
"image/jpg": "jpg",
};
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "public/uploads");
},
filename: function (req, file, cb) {
const filename = file.originalname.replace(" ", "-");
const extension = FILE_TYPE_MAP[file.mimetype]
cb(null, `${filename}-${Date.now()}.${extension}`);
},
});
Simple helpler function that maintains the unique filename generated by multer and adds the extension parsed from mimetype:
Just pass the object returned by multer
const fs = require('fs');
function renameWithExt(file) {
const ext = file.mimetype.split('/')[1]; // parse the extension type
fs.rename(`${file.path}`, `${file.path}.${ext}`, () => {
console.log(`File: ${file.filename} renamed with extension '.${ext}'`);
});
}
renameWithExt(req.file);
const storageAttach = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/attachFile')
},
filename: function(req, file, cb) {
let file_name_string = String(file.originalname).split('.')
let ext = file_name_string[file_name_string.length - 1]
console.log('file_storage', file.originalname.split('.')[file.origin]);
cb(null, file.fieldname + '-' + Date.now() + `.${ext}`) // set the extension to .jpg
}
})
const multer = require('multer');
const uuid = require('uuid/v1');
const MIME_TYPE_MAP = {
'image/png': 'png',
'image/jpeg': 'jpeg',
'image/jpg': 'jpg'
};
const fileUpload = multer({
limits: 500000,
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/images');
},
filename: (req, file, cb) => {
const ext = MIME_TYPE_MAP[file.mimetype];
cb(null, uuid() + '.' + ext);
}
}),
fileFilter: (req, file, cb) => {
const isValid = !!MIME_TYPE_MAP[file.mimetype];
let error = isValid ? null : new Error('Invalid mime type!');
cb(error, isValid);
}
});
module.exports = fileUpload;