nodejs multer uable to create directory and upload files - node.js

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..

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.

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

How can I convert cb error to json format in multer

I'm writing code for image upload in NodeJS using multer
My code is
var upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
cb(null, true);
} else {
return cb(JSON.stringify({ "success": false, "message": "invalid mime type" }), false);
}
}
});
router.post('/upload', upload.single('image'), (req, res, next) => {
const io = req.app.get('io');
const product = new db.product({
name: req.body.name,
category: req.body.category,
image: req.protocol + "://" + req.hostname + ":" + req.socket.localPort + "/img/roundtshirt/" + req.file.filename
});
});
When I upload an invalid file from Postman, I got the following error such as my callback
<pre>{"success":false,"message":"invalid mime type"}</pre>
However, I want to convert that error to proper json format.
I've tried returning json but got an error.
You can use custom error handling from Multer here
This is my example:
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
cb(null, true);
} else {
return cb(new Error('Invalid mime type'));
}
}
});
const uploadSingleImage = upload.single('image');
app.post('/upload', function (req, res) {
uploadSingleImage(req, res, function (err) {
if (err) {
return res.status(400).send({ message: err.message })
}
// Everything went fine.
const file = req.file;
res.status(200).send({
filename: file.filename,
mimetype: file.mimetype,
originalname: file.originalname,
size: file.size,
fieldname: file.fieldname
})
})
})
For the full example code, please visit https://gist.github.com/huynhsamha/348722d47ee457454688698ff77fee1a
Thank for reading :D

How to handle errors with multer?

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 });

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