File uploading in express using multer - node.js

I am trying to upload image using multer but getting error,uploads is not a function.Here is my code
var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single('image'), function(req, res) {
console.log(req.file);
var file = __dirname + '/' + req.file.filename;
uploads(req.file.path, file, function(err) {
if (err) {
console.log(err);
res.send(500);
} else {
res.json({
message: 'File uploaded successfully',
filename: req.file.filename
});
}
});

var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single('image'), function(req, res) {
yourModel.create(req.body,function(err,result){
console.log(result);
});
});

Its quite obvious; uploads is not a function but uplaod is. So use
upload.single('image')

As #Kuldeep said you don't have to the uploads(filePath, file, (err) => {...}) inside the route.
When you are using multer as middleware (the middle function) multer will automatically upload the file and expose the filename, originalName etc to req.file object inside the route
var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single('image'), function(req, res) {
// here just write the success or error login
});
Reference You can check here: here
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 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 });
Now you can use the uploads variable as middleware as shown in the above snippet.

I haven't found a great, soup-to-nuts guide on using Multer (the website is just a little lacking for newbies) so here's my stab at it.
After using:
npm install multer --save
to add it to your project.
For me, I wanted to capture files on a specific route, namely:
/customers/:id/upload
So, I went into my customers.js route file and added:
var multer = require('multer');
as well as the code to set up the storage (diskStorage) and filename configuration tweaks:
var storage=multer.diskStorage({
destination: function(req,file,cb){
cb(null,'/uploads/');
},
filename: function(req,file,cb){
cb(null,file.fieldname+'-'+Date.now());
}
});
I could then create the upload middleware object that lets me specify, per route, how I would like Multer to handle file uploads. On the route above, I only want to receive one file with a particular internal filename so my customers.js route file looks like this:
router.post('/:id/targets/upload', upload.single('connections'), function(req,res,next){
console.log("Router:POST: Companies/:_id/upload");
console.log(req.file);
...
});
All of the examples I saw had stuff being added to the app.js file but these seemed a bit awkward and contrived as examples. Every route may have different file handling needs so it just seemed more appropriate, to me, to configure Multer on a per-controller basis. YMMV.

Related

Write logic to wrap usage of Multer middlware (Express.js)

I'm using the multer middlware to upload files like so:
import multer from 'multer';
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, './');
},
filename: (req, file, callback) => {
callback(null, `${Date.now()}${file.originalname}`);
}
});
const uploadFile = multer({ storage });
export default uploadFile.single('file');
And the route I'm using the middlware from:
router.post('/upload--file', uploadFile);
The issue is, I want to to add some logic before saving the file, after saving it etc.
How should I do it? I'm confused as I can't edit the middleware itself obviously.
This solution is for error handling on multer but should answer your question on how to wrap the multer middleware to add your logic before the multer upload.
Link to solution

How to display uploaded image using multer?

I'm using nodejs as backend and vuejs as front. I've uploaded somes files as test using postman to my backend, but, how could I display these uploaded files using multer?
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
const upload = multer({ storage: storage }).single('logo');
router.post('/logo', auth.authorize, (req, res, next) => {
upload(req, res, (err) => {
});
res.status(200).send('uploaded');
});
I got an image named 'logo-1531296527722' in my api public folder. If I try to use it in my img src (http://localhost:3000/api/company/public/logo-1531296527722) it doesn't displayed. If I try to access this route I got this error Cannot GET /api/company/public/logo-1531296527722. In all questions about that, nodejs has its own html processor like ejs or jade, but I my case, nodejs is just serving my front and all images must be rendered using vuejs.
I dit it!
In my app.js I include app.use('/dist', express.static(path.join(__dirname + '/dist')));

How to render images which are stored using multer in express app?

I have stored images with multer on express app server. But I am not getting that images to use in my html files.
Code to upload file.
var multer = require("multer")
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, __dirname+'/public/uploads')
},
filename: function (req, file, cb) {
cb(null, Date.now()+file.originalname)
}
})
app.post('/add/details', upload.any(), function(req,res){
var data = req.body;
data.propic = req.files[0].path;
res.render('index',{
"data": data
});
})
In index file I am setting src of img to data.propic but it's not showing image.
you can use this
var fileUpload = require('express-fileupload');
router.use(fileUpload());
sampleFile = req.files.team_image;
file_name = sampleFile.name;
sampleFile.mv('public/storage/'+file_name, function(err) {
if (err) {
if (err) throw err;
}
});
Since you are saving the images in public/images folder, you can take advantage of express.static for serving these newly uploaded files automatically.
var express = require('express');
var multer = require("multer")
var app = express();
//all static contents inside the given folder will be accessible
//e.g. http://example.com/public/uploads/test.png
app.use(express.static(__dirname+'/public/uploads'));
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, __dirname+'/public/uploads')
},
filename: function (req, file, cb) {
cb(null, Date.now()+file.originalname)
}
});
app.post('/add/details', upload.any(), function(req,res){
var data = req.body;
// path of uploaded file.
data.propic = '/public/uploads/'+req.files[0].filename;
res.render('index',{
"data": data
});
});
Assume that you are using jade as view engine, you can embed img as following:
img(src=data.propic) // it's equivalent to http://example.com/public/uploads/test.png

Upload file to project specific directory dynamically in multer

I am trying to add a file upload feature in my MEAN.js application. I made use of multer, but it places all the files directly in the destination specified at the time of initializing multer. I want to upload files to directories specific to the program for which they are being uploaded (of course create directory dynamically if it doesn't exist). Where should I specify the custom logic of creating directories on the fly and placing files in them.
I tried a lot of solutions but nothing helped me.
Finally I wrote this and it works!
My solution (I am using express 4.13 and multer 1.2):
Imports:
var express = require('express');
var router = express.Router();
var fs = require('fs');
var multer = require('multer');
Storage variable (see documentation here)
var storage = multer.diskStorage({
destination: function (req, file, cb) {
var newDestination = 'uploads/' + req.params.__something;
var stat = null;
try {
stat = fs.statSync(newDestination);
} catch (err) {
fs.mkdirSync(newDestination);
}
if (stat && !stat.isDirectory()) {
throw new Error('Directory cannot be created because an inode of a different type exists at "' + dest + '"');
}
cb(null, newDestination);
}
});
Initializing Multer:
var upload = multer(
{
dest: 'uploads/',
limits: {
fieldNameSize: 100,
fileSize: 60000000
},
storage: storage
}
);
Using it!
router.use("/upload", upload.single("obj"));
router.post('/upload', controllers.upload_file);
You can't. However, you can move the file to other locations after the file is uploaded. That is probably your best bet. You could make your storage object a module and change the directory dynamically via init
var multer = require('multer'); // middleware for handling multipart/form-data,
// Constructor
module.exports = function (name) {
try {
// Configuring appropriate storage
var storage = multer.diskStorage({
// Absolute path
destination: function (req, file, callback) {
callback(null, './uploads/'+name);
},
// Match the field name in the request body
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
return storage;
} catch (ex) {
console.log("Error :\n"+ex);
}
}
I think the best solution to this problem is to use busboy, which let's you store your images in your desired location.
var Busboy = require('busboy');
var fs = require('fs');
app.post('.....',fucntion(req, res, next){
var busboy = new Busboy({ headers: req.headers });
busboy.on('field', function(fieldname, val) {
req.body[fieldname] = val;
});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
fstream = fs.createWriteStream("path/desiredImageName");
file.pipe(fstream);
fstream.on('close', function() {
file.resume();
});
})
return req.pipe(busboy);
})

express multer uploaded files url

probably a stupid question but maybe someone here could help me.
after uploading files with multer and express, what would be the url of the uploaded files to uploads/?
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
}
});
if it's an image, how can i link to it like:
http://localhost:3000/uploads/image.jpg?
should i place the uploaded files in the public directory?
thanks
This is how I setup Multer for expressjs. First you have to overwrite the renaming function if you want to keep the original filename. Then you have to move the uploads folder to the public folder.
// this uploads a single input[file] field called 'image'
var express = require('express'),
multer = require('multer'),
upload = multer({
storage: multer.diskStorage({
destination: 'public/images/uploads/',
filename: function(req, file, cb) {
// this overwrites the default multer renaming callback
// and simply saves the file as it is
cb(null, file.originalname)
}
})
}),
router = express.Router()
// add route
router.post('/uploadimage', upload.single('image'), function(req, res, next) {
if (!req.file) return next(new Error('Select a file!'))
// be careful here as the upload path has 'public' at the start
// which is the static mounted directory so doesn't show
// here the path is build manually
var imagePath = '/images/uploads/' + req.file.filename;
res.end('<img src=" + imagePath + " />')
})
additionally you can keep the default upload path as /uploads and mount it as a static folder
// Mount uploads
app.use(express.static(path.resolve('./uploads')));
Make static teh diskstoarge location in your case 'uploads' folder should be static
app.use(express.static('uploads'));
https://expressjs.com/en/starter/static-files.html

Resources