Same Image not uploading in express - node.js

I am trying to upload an image using express but I am facing two problems, first, whenever I upload the same image again it's not getting uploaded and secondly after uploading any single image a file with image also uploading. Here is my code.
var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single("file"), function (req, res) {
var file = __dirname +"/images" + "/" + req.file.originalname;
fs.readFile( req.file.path, function (err, data) {
fs.writeFile(file, data, function (err,data) {
if( err ){
console.error( err );
response = {
message: 'Sorry, file couldn\'t be uploaded.',
filename: req.file.originalname
};
}else{
response = {
message: 'File uploaded successfully',
filename: req.file.originalname
};
}
res.end( JSON.stringify( response ) );
});
});
})

The uploads.single("file") middleware Will handle the file upload. You don't have to specifically fs.read and fs.write the file.
var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single("file"), function (req, res) {
//the file is uploaded automatically
})
EDIT: The above code will upload the file with hex string as filename without any extension.
In order to add rename function you need to use diskStorage. Here is the code taken from this github issue page.
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './images/')
},
filename: function (req, file, cb) {
crypto.pseudoRandomBytes(16, function (err, raw) {
cb(null, raw.toString('hex') + Date.now() + '.' + mime.extension(file.mimetype)); //this is the rename func
});
}
});
var uploads = multer({ storage: storage });
app.post('/uploading', uploads.single("file"), function (req, res) {
//the file is uploaded automatically
})
Now you can use the uploads variable as middleware as shown in the above snippet.
you can edit the filename: function (req, file, cb) { .. } according to your needs. Now the filename will be, <16characterhexstring>.ext

another way to handle it will be not using middleware and using multer manually with below options :
try {
var storage = multer.diskStorage({
destination: function(request, file, callback) {
//define folder here by fs.mkdirSync(anyDirName);
},
filename: function(req, file, callback) {
callback(null, anyFileName);
},
limits: self.limits
});
var upload = multer({
storage: storage,
fileFilter: function(request, file, callback) {
// here you can filter out what not to upload..
}
}).any();
upload(request, response, callback);
} catch (e) {
}
hope this helps!

Related

Multer - handle missing file

I'm using multer as express middleware to upload a file like so:
const upload = multer().single('fieldName');
router.post(
'/',
upload,
(req, res) => {
console.log(req.file)
}
);
It works fine except when I sent the form without a file. Then apparently the upload middleware is just skipped and req.file is undefined.
I tried to add a filter like so but apparently the filter function is not called when there is no file:
function fileFilter(req, file, cb) {
console.log('filtering'); //never reached when file is missing
if (!file) {
return cb(new Error('no file', false));
}
cb(null, true);
}
const upload = multer({fileFilter: fileFilter}).single('fieldName');
router.post(...)
Is there any way to handle the missing file inside the multer middleware? Or do I have to check afterwards?
check in you html form "fieldName" in input name
and this can you help
in you routes app
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now()+'.mp3')
}
})
var upload = multer({ storage: storage })
router.post(
'/uploadfile',upload.single('fieldName'),
)

Multer is not working outside of the http object

I am using multer and it works fine in the http object, here is the code:
server = http.createServer(function(req, res){
var upload = multer({ storage : multerhelper.storage}).single('userFile');
upload(req, res, function(err) {
if(err)
console.log("Error uploading the file");
});
});
The moment I take this piece of code outside of the http object inside another file, it doesn't work anymore.
handlers._users.post = function(req, res, data, callback){
var upload = multer({ storage : multerhelper.storage}).single('userFile');
upload(req, res, function(err) {
if(err)
console.log("Error uploading the file");
callback(400, {'Message' : 'Done'});
});
});
Your help is appreciated.
You can make a file which will have the multer logic and export this file so that you can get the multer functionality.
example:
const multer = require("multer");
// store the file reference through multer
const storage = multer.diskStorage({
destination: function (req, file, callback) {
//Where file should be store
callback(null, __base + "/public/uploads");
},
filename: function (req, file, callback) {
callback(null, file.originalname);
}
});
//make sure file is image as the jpeg or png
const fileFilter = (req, file, callback) => {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/png" || file.mimetype === 'application/octet-stream') {
callback(null, true);
}
callback(null, false);
};
export const upload = multer({
storage,
limits: {
fileSize: 1024 * 1024 * 5000
},
fileFilter
});
Now import this file as
import {
upload
} from "/filepath";

Multer fileFilter is not getting called and req.body is empty

for some reason the fileFilter on multer is not getting called.
here is my Controller (i am using express routers)
const express = require('express');
const router = express.Router();
const UploadController = require('../controllers/UploadController');
router.route('/upload').post(UploadController.upload);
module.exports = router;
and this is the controller
const multer = require('multer');
const fs = require('fs');
module.exports = {
upload: function (req, res) {
let storage = multer.diskStorage({
destination: function (req, file, cb) {
console.log('here');
const filesDir = './uploads/' + req.body.ref;
if (!fs.existsSync(filesDir)) {
fs.mkdirSync(filesDir);
}
cb(null, filesDir);
},
filename: function (req, file, cb) {
let extArray = file.mimetype.split("/");
let extension = extArray[extArray.length - 1];
cb(null, req.body.type + '-' + Date.now() + '.' + extension);
},
fileFilter : function (req, file, cb) {
if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
return cb(new Error('Only image files are allowed!'), false);
}
cb(null, true);
}
})
const upload = multer({ storage: storage }).single('file');
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
res.send({
error: err
});
} else if (err) {
res.send({
error: err
});
}else{
res.send({
file: req.file,
body: req.body
});
}
});
}
}
I have following issues:
The fileFilter function is not even called so its not validating files
the req.body on the upload function (upload: function (req, res)) is empty it is only available in diskStorage and last upload function (upload(req, res, function (err)) so i cannot validate the body data also.
I had the same problem. the fileFilter function has to be defined inside multer, not inside the diskStorage function.
To make it a bit more readable I defined the storage and filter in variables instead of making everything inside the multer call.
// storage settings
const multerStorage = multer.diskStorage({
destination: function(req, file, next) {
next(null, './public/files');
},
filename: function(req, file, next) {
const sanitizedName = file.originalname
.replace('/[^a-z0-9\./gi', '-')
.replace('/-{2,}/g', '-')
.toLowerCase();
const name = Date.now() + '-' + sanitizedName;
// sending the file name to be stored in the database
req.body.filename = name;
next(null, name);
},
limits: {
fileSize: 25000000
}
});
// filter function
const multerFilter = function(req, file, cb) {
const ext = path.extname(file.originalname).toLowerCase();
if (ext !== '.pdf') {
cb(new Error('File must be in PDF format.'));
}
cb(null, true);
}
And then applying the storage settings and filter function to multer:
const upload = multer({
storage: multerStorage,
fileFilter: multerFilter
});

upload a xls file with postman to a RESTapi made with node/express

In node a can make something like this with and excel file in my directory.
app.post('/api/xlstojson', function(req, res) {
var workbook = XLSX.readFile('tc2.xls');
var sheet_name_list = workbook.SheetNames;
res.json(XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]));
});
I want to test file uploading with postman. There I select POST, form-data, in key I select file instead of text and then in value I upload the tc2.xls file.
In my code I have something like this
app.post('/api/xlstojson', function(req, res) {
var workbook = XLSX.readFile(req.body.file);
var sheet_name_list = workbook.SheetNames;
res.json(XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]));
});
But I get TypeError: path must be a string or Buffer. How should I modify my code to make this work?
Update:
I have been trying with multer, but the file does not appear in the folder
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/')
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1])
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');
app.post('/upload', function(req, res) {
upload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
});
});
TypeError: path must be a string or Buffer
You're getting this error because you're not passing the file location. For this to work, you need to pass the location of the file within the upload/ folder
'use strict';
const XLSX = require('xlsx');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads');
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length - 1]);
}
});
var upload = multer({ //multer settings
storage: storage
});
function validate(req, res, next) {
if (!req.file) {
return res.send({
errors: {
message: 'file cant be empty'
}
});
}
next();
}
app.post('/api/xlstojson', upload.single('file'), validate, function (req, res) {
const fileLocation = req.file.path;
console.log(fileLocation); // logs uploads/file-1541675389394.xls
var workbook = XLSX.readFile(fileLocation);
var sheet_name_list = workbook.SheetNames;
return res.json({
json: XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]])
});
});
You need to upload the xls file from postman

multer save image without mimetype

I'm using "multer": "^1.0.6", And i Want to save image in upload folder.
My code is
app.post('/post', multer({dest: './uploads/'}).single('file'), function (req, res) {
response = {
message: 'File uploaded successfully',
filename: req.file.filename
};
res.end(JSON.stringify(response));
});
But I Have the file with this name in upload folder 8e6e425f8756e0bafb40ed1a3cb86964
Why I have this name without mimetype?
Multer saves files without extensions you can read this on GitHub:
filename is used to determine what the file should be named inside the folder. If no filename is given, each file will be given a random name that doesn't include any file extension.
If you want to save with the extension that you write your code like here:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename: function (req, file, cb) {
cb(null, file.originalname); // modified here or user file.mimetype
}
})
var upload = multer({ storage: storage })
All information you can find here https://github.com/expressjs/multer/blob/master/README.md
Multer not worried about the extension of the file and leave it completely on your side: you have to define itself a function that will do it. For example, like this:
var multer = require('multer');
var upload = multer({ storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads');
},
filename: function (req, file, cb) {
var ext = require('path').extname(file.originalname);
ext = ext.length>1 ? ext : "." + require('mime').extension(file.mimetype);
require('crypto').pseudoRandomBytes(16, function (err, raw) {
cb(null, (err ? undefined : raw.toString('hex') ) + ext);
});
}
})});
app.post('/post', upload.single('file'), function (req, res) {
response = {
message: 'File uploaded successfully',
filename: req.file.filename
};
res.end(JSON.stringify(response));
});

Resources