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.
There may be some cases of files with no extension.
There should not be an upload.any() usage. Its vulnerable to the attackers
The upload function should not be global
.
I 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});
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 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;
Related
I am using multer for single file upload in 1 post field but what if i want to add 2 or more file inside different post field like below.
this is for different module.
so for single file upload i am using following code
var uploadfilename = "";
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './public/assets' + customStrings.FOLDER)
},
filename: (req, file, cb) => {
uploadfilename = Date.now() +
path.extname(file.originalname);
cb(null, uploadfilename);
}
});
var upload = multer({
storage: storage
});
and in post api route
router.post("/news", upload.single('image'), (req, res) => {
});
now if i want multiple field for file upload what we will do ??
i fount one solution for that is following
var uploadfilename = "";
var uploadCityfilename = "";
var storage = multer.diskStorage({
destination: (req, file, cb) => {
if (file.fieldname == "image") {
cb(null, './public/assets' + customStrings.FOLDER)
} else {
cb(null, './public/assets' + customStrings.CITY_FOLDER)
}
},
filename: (req, file, cb) => {
if (file.fieldname == "image") {
uploadfilename = Date.now() + "-" +
customStrings.IMAGE_POST_NAME + path.extname(file.originalname);
cb(null, uploadfilename);
} else {
uploadCityfilename = req.body.city + path.extname(file.originalname);
cb(null, uploadCityfilename);
}
}
});
var upload = multer({
storage: storage
});
and in post api route
router.post("/imageupload", upload.any(), (req, res) => {
});
it works for me :)
I am using body-parser to get info requested from forms, but when I put enctype="multipart/form-data" in the header of the form, the req.body will not working at all.
However, I have used multer lib in order to upload images as follow:
app.post("/", function (req, res, next) {
var button = req.body.button_name;
if (button == "upload") {
var UserId = 2;
var imageUploadedLimited = 3;
var storage = multer.diskStorage({
destination: function (req, file, callback) {
var dir = "./public/images/uploads/";
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
dir = "./public/images/uploads/" + UserId;
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
callback(null, dir);
},
filename: function (req, file, cb) {
cb(null, file.fieldname + "-" + Date.now() + ".jpg");
},
});
const maxSize = 1 * 1000 * 1000;
var upload = multer({
storage: storage,
limits: { fileSize: maxSize },
fileFilter: function (req, file, cb) {
var filetypes = /jpeg|jpg|png/;
var mimetype = filetypes.test(file.mimetype);
var extname = filetypes.test(
path.extname(file.originalname).toLowerCase()
);
if (mimetype && extname) {
return cb(null, true);
}
cb(
"Error: File upload only supports the " +
"following filetypes - " +
filetypes
);
},
}).array("filename2", imageUploadedLimited);
upload(req, res, function (err) {
if (err) {
res.send(err);
} else {
res.send("Success, Image uploaded!");
}
});
}
});
If I print out the button variable from the second line, will show me undefined value. I know body-parser does not support enctype="multipart/form-data". In this case, how I can see the value from the form?
If you are using multer, it needs to be passed as middleware
// Do Something like this
var multer = require('multer')
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'Your path here')
},
filename: function (req, file, cb) {
cb(null, "fileName")
}
})
var upload = multer({
storage: storage,
})
app.post("/" ,upload.any(), function (req, res, next) {
// NOW YOU CAN ACCESS REQ BODY HERE
});
I'm using a multer api, and I'm saving files in memory, because I need to upload images and pdf, and I need to process the images.
I can upload images, but I can't upload pdfs files.
Thanks
well, this is my code... I really hope to help you.
const express = require('express');
const multer = require('multer');
const app = express();
const storage =
multer.diskStorage({
destination: path.join(__dirname, 'public/img/'), // destination folder
filename: (req, file, cb) => {
cb(null, uuid.v4() + path.extname(file.originalname));
}
});
const upload =
multer({
storage,
dest: path.join(__dirname, 'public/img/'), // destination folder
limits: {fileSize: 3500000}, // size we will acept, not bigger
fileFilter: (req, file, cb) => {
const filetypes = /jpeg|jpg|png|gif|pdf/; // filetypes you will accept
const mimetype = filetypes.test(file.mimetype); // verify file is == filetypes you will accept
const extname = filetypes.test(path.extname(file.originalname)); // extract the file extension
// if mimetype && extname are true, then no error
if(mimetype && extname){
return cb(null, true);
}
// if mimetype or extname false, give an error of compatibilty
return cb("The uploaded file, isn't compatible :( we're sorry");
}
}).single('image'); // This is the field where is the input type="file", we only accept 1 image
app.use(upload);
and the view will looks like this
app.post('/add', async (req, res) => {
const { originalname, mimetype, destination, filename, path, size} = req.file;
const newImage = {
originalname,
mimetype,
destination,
filename,
path,
size
};
await pool.query('Insert Into imagen set ?', [newImage]);
res.send('image uploaded');
});
this might help you
// Set storage engine
const storage = multer.diskStorage({
destination: "./uploads",
filename: function(req, file, cb) {
// null as first argument means no error
cb(null, Date.now() + "-" + file.originalname);
},
});
let encode_file = null;
let fileName = "";
if (req.file) {
fileName = req.file.originalname;
var filepath = path.join(__dirname, req.file.path);
console.log(filepath);
var stream = fs.readFileSync(filepath);
encode_file = stream.toString("base64");
}
I want to upload a zip file into the server using node.So can any one help me to figure it out.
First upload your zip file using Multer:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
var upload = multer({ storage: storage })
Then unzip it using unzipper module:
1) Install unzipper module
npm i unzipper
2) ExtractZip.js JavaScript
const unzipper = require('./unzip');
var fs = require('fs');
fs.createReadStream('path/to/archive.zip')
.pipe(unzipper.Parse())
.on('entry', function (entry) {
const fileName = entry.path;
const type = entry.type; // 'Directory' or 'File'
const size = entry.vars.uncompressedSize; // There is also compressedSize;
if (fileName === "this IS the file I'm looking for") {
entry.pipe(fs.createWriteStream('output/path'));
} else {
entry.autodrain();
}
});
// Source
Test:
c:\Samim>node ExtractZip.js
You can try multer
npm install --save multer
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
var upload = multer({ storage: storage })
I'm using multer to upload files. everything is goung fine but fileFilter is not working. I've no idea where i'm going wrong.
routes.js
var multer = require('multer');
// Multer diskStorage setting
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads/');
},
filFilter: function (req, file, cb) {
var typeArray = file.mimetype.split('/');
var fileType = typeArray[1];
if (fileType == 'jpg' || fileType == 'png') {
cb(null, true);
} else {
cb(null, false)
}
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '_' + Date.now() + '.jpg');
}
});
var upload = multer({ storage: storage });
router.post('/add', upload.single('photo'), function(req, res){
console.log('uploaded');
}
Multer also uploads files other than allowed. Any idea?
fileFilter must be defined in multer's options object rather than diskStorage
const uploadFilter = function(req, file, cb) {
// filter rules here
}
const upload = multer({
storage: storage,
fileFilter: uploadFilter,
});
const storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads/');
},
fileFilter: function (req, file, cb) {
const extension = path.extname(file.originalname).toLowerCase();
const mimetyp = file.mimetype;
if (
extension !== '.jpg' ||
extension !== '.jpeg' ||
extension !== '.png' ||
mimetyp !== 'image/png' ||
mimetyp !== 'image/jpg' ||
mimetyp !== 'image/jpeg'
) {
cb('error message', true);
}
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '_' + Date.now() + '.jpg');
},
});
const upload = multer({ storage: storage });
router.post('/add', upload.single('photo'), function (req, res) {
console.log('uploaded');
});
i think this will help
You have a typo at your fileFilter; you've named it filFilter.
Could you change your code to the following and tell us if it worked out?
var multer = require('multer');
// Multer diskStorage setting
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads/');
},
fileFilter: function (req, file, cb) {
var typeArray = file.mimetype.split('/');
var fileType = typeArray[1];
if (fileType == 'jpg' || fileType == 'png') {
cb(null, true);
} else {
cb(null, false)
}
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '_' + Date.now() + '.jpg');
}
});
var upload = multer({ storage: storage });
router.post('/add', upload.single('photo'), function(req, res){
console.log('uploaded');
}