How to handle errors with multer? - node.js

I need to upload images on server, but if it is not jpeg\png, or filesize > 10Mb, I need to show an error. Images uploading well, but when I am trying to upload .zip file, my console is empty, why my code can't handle an error?
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../public/img/avatars')
},
filename: function (req, file, cb) {
cb(null, ''+req.user._id+'')
},
fileFilter: function (req, file, cb) {
if (file.mimetype !== 'image/png' && file.mimetype !== 'image/jpg' && file.mimetype !== 'image/gif' ) {
console.log('Wrong format!');
return cb(null, false, new Error('Wrong format!'));
}
if ( file.size > 10000 ){
console.log('Too large!');
return cb(null, false, new Error('Too large!'));
}
cb(null, true);
}
});
var upload = multer({ storage: storage });
router.post('/changeAvatar', upload.single('avatar'), function(req, res) {
var id = req.user._id;
res.redirect('/user/'+id);
});

Done. Just remove fileFilter from storage function.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../public/img/avatars')
},
filename: function (req, file, cb) {
cb(null, ''+req.user._id+'')
}
});
function fileFilter(req, file, cb) {
if (file.mimetype !== 'image/png' && file.mimetype !== 'image/jpg' && file.mimetype !== 'image/gif' ) {
console.log('Неправильный формат изображения!');
return cb(null, false);
}
if ( file.size > 10000 ){
console.log('Изображение весит слишком много!');
return cb(null, false);
}
cb(null, true);
}
var upload = multer({ storage: storage, fileFilter: fileFilter });

Related

How to delete a video file if the user interrupted the download?

I am doing file uploads using a Multer.
When the file has successfully uploaded, I get the path to the video and can delete it, but if the user interrupted the download, the Multer still uploads part of the file to the downloads folder, but does not give the path to the video file, how can I delete such files in this case ?
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'upload/');
},
filename: function (req, file, cb) {
cb(null, `${req.user.id}-${Date.now()}-${file.originalname}`);
}
});
const fileFilter = (req, file, cb) => {
if(
file.mimetype === 'image/png' ||
file.mimetype === 'image/jpg' ||
file.mimetype === 'image/jpeg' ||
file.mimetype === 'video/mp4'
) {
cb(null, true);
} else {
cb(null, false);
}
};
const uploadConfig = multer({
storage: storage,
fileFilter: fileFilter,
limits: {fileSize: 1000000000 * 10},
preservePath: true
});
router.post('/upload-content', isAuth, uploadConfig.any(), async (req, res, next) => {
try {
res.status(201).json({
message: 'Saved successful',
contentType: req.files[0].mimetype,
fileName: req.files[0].filename,
fileOriginalName: req.files[0].originalname,
fileSize: req.files[0].size,
filePath: req.files[0].path
})
} catch (err) {
console.log(err);
}
})
Unfortunately, this is a multer-issue that has been around for a couple of years now, see this related github issue: https://github.com/expressjs/multer/issues/259
I suggest you try to implement one of the proposed workarounds, we're using the same in our app and it has been working fine so far.

nodejs multer uable to create directory and upload files

I have used middleware - upload which returns error after giving both received files in log:
Error: ENOENT no such file or directory open, C:\{path here}
uploaddata.js:
const express = require("express");
const multer = require("multer");
/* const router = express.Router();
router.use(express.static(__dirname+"uploads/")); */
const Storage = multer.diskStorage({
destination: function(req, file, callback) {
console.log("file.fieldname", file);
callback(null, 'uploads/'+file.fieldname+'/');
},
filename: function(req, file, callback) {
console.log("filename::", file.originalname);
callback(null, file.fieldname + "_" + Date.now() + "_" + file.originalname);
}
});
const upload = multer({
storage: Storage,
limits: {
fileSize: 1024 * 1024
},
fileFilter: (req, file, cb) => {
checkFileType(file, cb);
}
}).fields(
[
{
name:'userpic',
maxCount:1
},
{
name:'usercv',
maxCount:1
}
]
);
function checkFileType(file, cb) {
// console.log("file.fieldname", file);
if(file.fieldname==="userpic")
{
if (file.mimetype === 'image/png' || file.mimetype === 'image/jpg' || file.mimetype === 'image/jpeg')
{ // check file type to be png, jpeg, or jpg
cb(null, true);
} else {
cb(null, false); // else fails
}
}
if(file.fieldname==="usercv")
{
if ( file.mimetype === 'application/pdf' || file.mimetype === 'application/msword' || file.mimetype === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' )
{ // check file type to be pdf, doc, or docx
cb(null, true);
} else {
cb(null, false); // else fails
}
}
}
module.exports = upload;
in console via postman I am sending image and docx file which is reading successfully but it unable to create directory and those files on server path
can any one gives me solution..

Multer Muti Upload Image With Express

I use React and Express for create Mutiupload Image
multer.js
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/')
},
filename: function (req, file, cb) {
cb(null, new Date().toISOString() + '-' + file.originalname)
}
})
const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true)
} else {
//reject file
cb({message: 'Unsupported file format'}, false)
}
}
const upload = multer({
storage: storage,
limits: { fileSize: 1024 * 1024 },
fileFilter: fileFilter
})
module.exports = upload;
post.controller.js
async onInsert(req, res) {
try {
let result = await Service.insert(req.body)
res.success(result, 201);
} catch (error) {
res.error(error.message, error.status)
}
},
post.service.js
insert(data) {
return new Promise(async(resolve, reject) => {
try {
const obj = new Post(data)
let inserted = await obj.save()
resolve(inserted)
} catch (error) {
reject(methods.error(error.message, 400))
}
});
},
I try to implements Multer on this controller but it can't upload anyway . so how to implements mutiple upload image with this code thank
I use mongoose by the way
const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'images');
},
filename: (req, file, cb) => {
cb(null, new Date().toISOString().replace(/:/g, '-') + file.originalname);
}
});
const fileFilter = (req, file, cb) => {
if (
file.mimetype === 'image/png' ||
file.mimetype === 'image/jpg' ||
file.mimetype === 'image/jpeg'
) {
cb(null, true);
} else {
cb(null, false);
}
};
const csrfProtection = csrf();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(
multer({ storage: fileStorage, fileFilter: fileFilter }).fields(
[
{
name: 'image1',
maxCount: 1
},
{
name: 'image',
maxCount: 1
},
{
name: 'passbook',
maxCount: 1
},
{
name:'certificate',
maxCount:1
}
]
)
);
in controller
const image=req.files.image1;
const passbook=req.files.passbook;
const certificate=req.files.passbook;
if (!image || !passbook || !certificate) {
console.log("img err");
return res.redirect('admin/');
}
const imageUrl = image[0].path;
const passbookUrl= passbook[0].path;
const certificateUrl= certificate[0].path;
this works for me but i have only used Nodejs

Multer file filtering based on MIME type

I have the code below. I would like use multer to accept only documents with the MIME type for docx. Otherwise, I would like to produce an error. I plan on doing vetting on the front-end as well, but for security purposes would like to implement here as well. The following code is returning an error, can anybody tell me where i am wrong?
const multer = require('multer')
const fs = require('fs')
const upload = multer({
dest: './upload',
fileFilter: function (req, file, cb) {
if (req.file.mimetype != 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
return cb(new Error('Wrong file type'))
}
cb(null,true)
}
}).single('file');
app.post('/upload', upload, function(req, res) {
console.log(req.file);
};
It worked for me when I used file.mimetype instead of req.file.mimetype.
fileFilter: function (req, file, cb) {
if (file.mimetype != 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
return cb(new Error('Wrong file type'));
}
cb(null, true)
}
Hope that helped.
You can try following code snippet to accept only file type of docx:
const filefilter = (req, file, cb) => {
if (
file.mimetype === "application/msword" ||
file.mimetype ===
"application/vnd.openxmlformatsofficedocument.wordprocessingml.document"
) {
cb(null, true);
} else {
cb(null, false);
}
};

stop the file upload in multer if the user validation fails

The file uploading is done by multer by using this code, but how to stop the file upload when the user validation fails. where to write the user validation part in this code
router.post('/profilePicture',
multer({dest: './uploads/',
rename: function (fieldname, filename,req,res) {
return image = req.body.userId+'-'+dateTime+'-'+randomId();
},
onFileUploadStart: function (file,req,res) {
if(file.mimetype !== 'image/jpg' && file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/png') {
imageUploadDone = false;
return false;
}
//console.log(file.originalname + ' is starting ...');
},
onFileUploadComplete: function (file,req,res) {
//console.log(file.fieldname + ' uploaded to ' + file.path);
if(file.mimetype == 'image/jpg')
extn = '.jpg';
if(file.mimetype == 'image/jpeg')
extn = '.jpeg';
if(file.mimetype == 'image/png')
extn = '.png';
imageUploadDone=true;
}
}),function(req, res) {
upload(req,res,function(err) {
if(imageUploadDone==true){
//console.log(image);
var userInfo = {'userId':req.body.userId,'newImage':address+image+extn,'path':'./uploads/'};
db.profilePicture(userInfo,function(result){
if(result.message == 'image path added'){
res.json({'success':'1','result':{'message':'Profile Picture Updated','imageUrl':address+image+extn},'error':'No Error'});
}
});
}
if(imageUploadDone == false){
res.json({'success':'0','result':{},'error':'file format is not supported'});
}
});
});
i try to validate the user on the events like onFileUploadStart and onFileUploadComplete. if user is not valid still the file gets uploaded to the path.
This is now possible in 1.0.0.
If you want to abort the upload:
multer({
fileFilter: function (req, file, cb) {
if (path.extname(file.originalname) !== '.pdf') {
return cb(new Error('Only pdfs are allowed'))
}
cb(null, true)
}
})
If you want to skip any files that is not pdf:
multer({
fileFilter: function (req, file, cb) {
if (path.extname(file.originalname) !== '.pdf') {
return cb(null, false)
}
cb(null, true)
}
})
What you can do to validate the format of file : In your app.js put this code
const multer = require('multer');
/* defined storage and filename */
const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "images");
},
filename: (req, file, cb) => {
cb(null, new Date().toISOString() + "-" + file.originalname);
}
});
/* defined filter */
const fileFilter = (req, file, cb) => {
if (
file.mimetype === "image/png" ||
file.mimetype === "image/jpg" ||
file.mimetype === "image/jpeg"
) {
cb(null, true);
} else {
cb(new Error("File format should be PNG,JPG,JPEG"), false); // if validation failed then generate error
}
};
app.use(
multer({ storage: fileStorage, fileFilter: fileFilter }).single("image")
);
Now whenever your file is uploaded by key 'image' its format will be checked, if not satisfied then error will be generated.
Hope this will help to someone!
If you want to do file related validation, i.e mime type or file size, you can do this with fileFilter.
multer({
fileFilter: function(req, file, cb) {
// file validation...
}
});
The only problem with the above method is that you cannot do validations against the body of the request. req.body is empty inside the fileFilter callback as explained in this Github issue.
There is a workaround for this, which is described in this Github issue. This is not an optimal solution IMO because it forces the client to ensure validation.
Another option is to let the file be saved and then do your validation checks on req.body, if the request is invalid you can use something like del or rimraf to delete the persisted file from disk.
Another way of addressing this problem.
const path = require('path');
multer({
fileFilter: function (req, file, cb) {
var filetypes = /jpeg|jpg/;
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);
}
});
There is a further discussion about this issue on following link.
https://github.com/expressjs/multer/issues/114

Resources