routes.js
module.exports=function(app, upload){
var postingsController=require('../controllers/postings.server.controller');
app.post('/postings', postingsController.savePosting);
}
controller.js
var multer=require('multer');
exports.savePosting=function(req, res, next){
// this diskstorage function is not at all executed
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
console.log(file);
cb(null, file.filename + '.' + 'jpg');
}
});
var upload = multer({ storage: storage });
upload.single('attachment');
res.json({ message: "success" });
}
can someone tell me which line exactly uploads file. DO i write multer diskstorage configuration in main express configuration file or can i write any where. By the way i able to see json response which is from the line
Typically the middleware is created and inserted outside of any actual route handlers. For example:
routes.js
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
console.log(file);
cb(null, file.filename + '.' + 'jpg');
}
});
var upload = multer({ storage: storage });
module.exports = function(app, upload) {
var postingsController = require('../controllers/postings.server.controller');
app.post('/postings',
upload.single('attachment'),
postingsController.savePosting);
};
controller.js
exports.savePosting = function(req, res, next) {
// Use `req.file` to access attachment
if (req.file)
res.json({ message: "success" });
else // no file uploaded
res.json({ message: "failure" });
};
Multer is a middleware, which means it is added as a parameter to your route in most cases. So what the actual syntax would be like is:
app.post ("/postings", multer ({ ... }), postingsController.savePosting);
Multer gets called inbetween the request to "/postings" and the final function to do all the file work for you. It will then provide you with all the information via
req.files["fileInputName"]
in the following middlewares (your function is a "middleware", too).
Related
I am trying to upload different types of files to server using multer in an express application. But every time server responds by stating TypeError: req.files is not iterable . I checked and req.files is empty.
Here is the code for the same:
var express = require('express');
var app = express();
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() + '-' + file.originalname)
}
})
var upload = multer({ storage: storage }).array('userfiles', 10);
app.post('/upload', function (req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
return res.status(500).json(err);
} else if (err) {
// An unknown error occurred when uploading.
return res.status(500).json(err);
}
let uploadedFiles = [];
for (let item of req.files) {
uploadedFiles.push({ filename: item.originalname });
}
// Everything went fine.
res.json({ progress: 100, files: uploadedFiles });
})
});
app.listen(8000, (err) => {
if (err) {
console.log('ERROR:', err);
} else {
console.log('working on http://localhost:8000');
}
})
And this is how I am calling this API from postman:
Postman UI
I am unable to figure out where the problem is. Please help me with this.
I ran his code and he tried to store the images at the root of my filesystem.
to refer a a path relative to your current directory you need to use ./
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/') // change 'upload/' to './uṕload'
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname)
}
})
After this, the code worked.
i use multer according to it's readme file in github
it's readme said call multer in middleware like this:
app.js
var multer = require('multer')
app.post('/upload', upload.single('image'), function(req, res){})
but i defined my function(req, res) in another file - post.js - and my code in app.js looks like this:
app.post('/upload', upload.single('image'), post.new)
how can i require multer only on post.js, almost like this:
post.js
var multer = require('multer')
module.exports.new = function(req, res){
//access to req.file
}
app.js
app.post('/upload', post.new)
I can think of two ways.
Firstly, you could expose new as an array:
module.exports.new = [upload.single('image'), function(req, res) {
...
}];
Secondly, you could use multer within your function:
var imageUpload = upload.single('image');
module.exports.new = function(req, res) {
imageUpload(req, res, function(err) {
// Put the rest of your code here
});
};
In this second approach we're just invoking the multer middleware function ourselves, passing it our own function to use as the next callback. There's a little bit more information about doing this at https://github.com/expressjs/multer#error-handling though it describes the technique in a slightly different context.
For MVC structure You can simply do this by :
function Uploader(req, res, next) {
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, your_path);
},
filename: function (req, file, cb) {
cb(null, filename)
}
});
var upload = multer({
storage: storage
});
return upload;
}
module.exports = Uploader
In another file you can simply use
app.post('/upload', Uploader.single('image'), function(req, res){})
If you don't want to create function, you can do the following:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, upload_filePath)
},
filename: function (req, file, cb) {
cb(null,filename)
}
})
var upload= multer({
storage : upload
})
module.exports.upload=upload;
Both gives same result but using Function is more appropriate way.
I want to upload images using multer. But it is not working. What is wrong here?
This code is in my route file.
var multer = require('multer');
var upload = multer({ dest: 'public/uploads/' });
And this is my post route.
router.post('/addNewFood', upload.single('avatar'),function (req, res, next) {
console.log(req.files);
});
Try this, it works for me. Used express and node.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
});
var upload = multer({ storage: storage }).single('avatar');
router.post('/addNewFood', //Your authentication check,//
function (req, res, next) {
upload(req, res, function(err) {
if (err) {
res.redirect(req.headers.referer + "/error.html");
return;
}
if (!req.files) {
res.redirect(req.headers.referer + "/error.html");
return;
} else {
//Implement your own logic if needed. Like moving the file, renaming the file, etc.
res.redirect(req.headers.referer);
}
});
}
);
Make sure you install the package
npm install --save multer
You can try the following way,
In the server side, In your routes or controller file configure the multer:
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/images/uploads')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname)
}
})
var upload = multer({ storage: storage });
In the storage object,
destination is stand for, where the file will be uploaded. So make sure in your project directory, /public/images/uploads path is created. Otherwise you may want to change the file path.
Also in storage object filename is stands for, what will be the uploaded file name. Here I add the current time with the original file name to make the all file name unique.
Now in your desired routing, suppose
router.post('/', upload.single('image'), (req, res) => {
//here your other task.
});
Now your file is uploaded. Make sure the client side is using the same name, In this case 'image'.
<input type="file" name="image" id="image" class='form-control'>
This is a single file upload procedure.
For multiple files
router.post('/', upload.array(), function (req, res, next) {
//your task goes here
});
For more information, check this link.
const multer = require("multer");
function fileFilter(req, file, cb) {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/jpg" || file.mimetype === "image/png") {
cb(null, true)
} else {
cb(null, false)
}
cb(new Error('I don\'t have a clue!'))
}
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
cb(null, file.fieldname + '-' + uniqueSuffix)
}
})
var upload = multer({
storage: storage, limits: {
fieldSize: 1024 * 1024 * 5,
fileFilter: fileFilter
}
})
router.post("/", upload.single("image_url"),(req, res) => {
const new User=new User({
image_url: req.file.path
})
I was able to move a very simple middleware (isAuthenticated) over to an external middleware file, but I'm having a harder time with moving my multer upload over. I just learned how to move them to seperate files, so it's probably obvius.
routes/index.js
var middleware = require('../middleware/common');
var isAuthenticated = middleware.isAuthenticated;
var upload = middleware.multerSetup;
...
router.post('/updateuser',
upload,
...,
function (req, res, next) {
res.redirect('/dashboard');
}
);
--
//middleware/common.js
var multer = require('multer');
Middleware = {
//Checks whether user is logged in
isAuthenticated: function(req,res,next){
if(req.isAuthenticated()){
return next();
}
req.flash('auth',"You do not have the proper permissions to access this page");
res.redirect('/');
},
multerSetup: function(req,res,next){
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/')
},
//detects file type, then adds extension to match file type
filename: function (req, file, cb) {
var ext = "";
switch(file.mimetype){
case 'image/png':
ext = '.png';
break;
case 'image/jpeg':
ext = '.jpeg';
break;
default:
ext = '';
}
cb(null, Date.now() + ext); //Appending .jpg
}
});
var upload = multer({storage:storage, fileFilter: function (req, file, cb) {
var acceptedExt = ['.png','.jpg','.gif','.bmp'];
if (req.hasOwnProperty('file') && acceptedExt.indexOf(path.extname(file.originalname))=== -1) {
return cb(new Error('Image type not allowed: ' + path.extname(file.originalname)));
}
cb(null, true)
}});
return upload.single('upl');
}
};
module.exports = Middleware;
Error:
routes\index.js:108
upload.single('upl'),
^
TypeError: upload.single is not a function
at Object.<anonymous> (C:\Users\Tyler\WebstormProjects\volunteer\volunteerApp\routes\index.js:108:12)
You're setting up your multer middleware wrong. Your Middleware.multerSetup is a middleware function, which is then calling upload.single to set up multer (which is then never called and the request is left hanging). Move your multer upload setup outside your custom middleware and have your module export just the return function from upload.single.
Example:
Middleware = {
...
multerSetup: upload.single('upl')
...
}
Got it! Just needed to define upload in routes/index.js as a function.
var upload = middleware.multerSetup();
Brother in the separate file, declare your setup function, then your middleware and export it, and pass the "file" as a parameter in upload function and return upload.single(file):
const multer = require("multer");
function multerSetup() {
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "images");
},
filename: (req, file, cb) => {
cb(null, file.originalname);
},
});
return storage;
}
Middleware = {
upload: function (file) {
const upload = multer({ storage: multerSetup() });
return upload.single(file);
},
};
module.exports = Middleware;
In your route file write your route:
const router = require("express").Router();
const Middleware = require("../helper/uploadImages");
router.post("/", Middleware.upload("file"), (req, res) => {
res.status(200).json("file has been uploaded!");
});
module.exports = router
in index.js file just you need to import your route and use it:
const uploadImageRoute = require("./routes/uploadImages");
app.use("/api/upload", uploadImageRoute);
I'm trying to upload a file from a HTML form using Express.js and Multer. I've managed to save the file to the desired location (a folder named uploads).
However, I'd like to rename the file while uploading it because, by default, Multer gives it a strange name such as:
5257ee6b035926ca99923297c224a1bb
Might be a hexadecimal time stamp or so but I need a more explicit name in order to call a script on it later.
I've followed the explanation found here but it doesn't do anything more than it used to: uploading the file with the hexa name.
Also, the two events onFileUploadStart and onFileUploadComplete never seem to be triggered as I don't get anything logged in my console.
I am using two separate files for the server and the routing:
app.js
/**
* Dependencies
*/
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
/**
* Importation of routes
*/
var routes = require('./routes/index');
var recog = require('./routes/recog');
/**
* Express
*/
var app = express();
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// pour contrer les erreurs de cross domain
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', '*');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
/**
* Routes
*/
app.use('/', routes);
app.use('/recog', recog);
module.exports = app;
recog.js
/**
* Requirements
*/
var express = require('express');
var router = express.Router();
var multer = require('multer');
var uploads = multer({
dest: 'uploads/',
rename: function (fieldname, filename) {
console.log("Rename...");
return filename + Date.now();
},
onFileUploadStart: function () {
console.log("Upload is starting...");
},
onFileUploadComplete: function () {
console.log("File uploaded");
}
});
/**
* Upload d'une image
*/
router.post('/upload', uploads.single('image'), function (req, res, next) {
console.log("Front-end is calling");
res.json({status: 'success', data: 'Fichier chargé.\nOrgane sélectionné : ' + req.body.organ});
});
module.exports = router;
I have been digging around but I can't figure out what the problem is as I am quite new to Node.js and JavaScript in general.
Thanks for your help guys!
The usage for Multer has changed.
Currently Multer constructor accepts only three options:
dist/storage
fileFilter
limits
now rename, onFileUploadStart, onFileUploadComplete would not work.
however renaming can be done using DiskStorage
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 })
have a look at these links:
https://github.com/expressjs/multer
multer callbacks not working ?
I know this post is dated. I want to contribute to those who may arrive later. Below is a full functional server script to handle multiple uploaded pictures with random saved pictures names and file extension.
var express = require("express");
var multer = require("multer");
var app = express();
var path = require("path");
var uuid = require("uuid");
// Allow cross origin resource sharing (CORS) within our application
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploadedimages/')
},
filename: function (req, file, cb) {
cb(null, uuid.v4() + path.extname(file.originalname));
}
})
var upload = multer({ storage: storage })
// "files" should be the same name as what's coming from the field name on the client side.
app.post("/upload", upload.array("files", 12), function(req, res) {
res.send(req.files);
console.log("files = ", req.files);
});
var server = app.listen(3000, function() {
console.log("Listening on port %s...", server.address().port);
});
try this way which i'm using
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
console.log(file);
var fileObj = {
"image/png": ".png",
"image/jpeg": ".jpeg",
"image/jpg": ".jpg"
};
if (fileObj[file.mimetype] == undefined) {
cb(new Error("file format not valid"));
} else {
cb(null, file.fieldname + '-' + Date.now() + fileObj[file.mimetype])
}
}
})
var upload = multer({ storage: storage })
we give a random name to file with the help of date and appends the original file extension with help of file.mimetype
try console.log(file.mimetype) you will get the file name and extension separated by '/' then I split it to array and fetch the extension from it.
Try the below code.
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 })
File has structure like this:
{
"fieldname": "avatar",
"originalname": "somefile.pdf",
"encoding": "7bit",
"mimetype": "application/pdf",
"destination": "./uploads",
"filename": "36db44e11b83f4513188f649ff445a2f",
"path": "uploads\\36db44e11b83f4513188f649ff445a2f",
"size": 1277191
}
The next example saves file with it's original name an extension and not with the strange name like it is by default.
(Instead of "file.originalname" you can save it as you want)
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads') //Destination folder
},
filename: function (req, file, cb) {
cb(null, file.originalname) //File name after saving
}
})
var upload = multer({ storage: storage })
Personally I implemented the following solutions, which generates a random name for files and appends the original file extension (I assume that my extension is after the last . )
var path = require('path');
var options = multer.diskStorage({ destination : 'uploads/' ,
filename: function (req, file, cb) {
cb(null, (Math.random().toString(36)+'00000000000000000').slice(2, 10) + Date.now() + path.extname(file.originalname));
}
});
var upload= multer({ storage: options });
router.post('/cards', upload.fields([{ name: 'file1', maxCount: 1 }, { name: 'file2', maxCount: 1 }]), function(req, res, next) {
/*
handle files here
req.files['file1']; //First File
req.files['file2']; //Second File
req.body.fieldNames;//Other Fields in the form
*/
});
In the MULTER documentation you'll find this:
The disk storage engine gives you full control on storing files to
disk.
There are two options available, destination and filename. They are
both functions that determine where the file should be stored.
Note: You are responsible for creating the directory when providing
destination as a function. When passing a string, multer will make
sure that the directory is created for you.
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.
Note: Multer will not append any file extension for you, your function
should return a filename complete with an file extension.