Write logic to wrap usage of Multer middlware (Express.js) - node.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

Related

I have a problem when I tried to upload multiple files in node.js using multer

I'm trying to build a service that allows me to upload files I started with single-file uploading but I have an issue when I try to upload multiple files.
In short, my problem is that if I want to upload more than one image, it appears in the storage folder and I don't see the records in my DB.
Example of single-file upload record
Example of multi-file upload record
But those files are saved on my storage
There are two function in multer:
For single file to upload use:
upload.single('avatar')
For multiple file to upload use:
upload.array('photos', 12) //here 12 is max number of files to upload.
Refer to the following sample code:
const express = require("express");
const multer = require("multer");
const app = express();
const multerStorage = multer.memoryStorage();
// Filter files with multer if you need
const multerFilter = (req, file, cb) => {
if (file.mimetype.startsWith("image")) {
cb(null, true);
} else {
cb("upload only images.", false);
}
};
const upload = multer({
storage: multerStorage,
fileFilter: multerFilter,
});
app.post('/singleUpload', upload.single('avatar'), function (req, res,
next) {
// req.body will hold the text fields, if there were any
console.log(req.file);//req.file is the `avatar` file. here avatar is
input field name
})
app.post('/multipleUpload', upload.array('photos', 12), function (req,
res, next) {
// req.body will contain the text fields, if there were any
// req.files is array of `photos` files.here avatar is
input field name
console.log(req.files);
})

Endpoint in node.js that receives a file and stores it locally

How can I create a endpoint in node.js (localhost:8000/file) that receives files and stores them somewhere locally.
You can use multer npm module for this
Write a middleware named upload.js in express which will upload your file to your server
upload.js
const multer = require('multer');
const maxSize = 10 * 1024 * 1024;
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads')
},
filename: (req, file, cb) => {
cb(null, file.originalname)
},
});
const upload = multer({
storage: storage
});
module.exports = upload;
This will upload your file to your server.You need to call it in your route
app.js
const upload = require('./upload.js')
router.post("/files", upload.single('file'), (req,res)=>{
console.log("This is file ",req.file)
});
Make a folder named uploads and all files will be in uploads folder.

File uploading in express using multer

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.

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

Configuring multer to upload files to nodejs server

The express Router is setup as such:
var router = require('express').Router();
var multer = require('multer');
var uploading = multer({
dest: './uploads/',
limits: {fileSize: 1000000, files:1},
});
router.post('/upload', uploading.single('avatar'), function(req, res) {
console.log('success');
});
module.exports = router;
I am attempting to upload files:
curl -F "image=#/Users/runtimeZero/Desktop/nassau.jpg" localhost:3000/auth/upload
The express server throws the below error:
Error: Unexpected field
at makeError (/Users/.../node_modules/multer/lib/make-error.js:12:13)
at wrappedFileFilter (/Users/../node_modules/multer/index.js:39:19)
...
...
at HeaderParser.push (/Users/.../node_modules/multer/node_modules/busboy/node_modules/dicer/lib/HeaderParser.js:46:19)
at Dicer._oninfo (/Users/.../node_modules/multer/node_modules/busboy/node_modules/dicer/lib/Dicer.js:197:25)
From multer documents this seems pretty straight forward. However, not so much when actually using it. What am i missing ?
If you look at the multer readme you will see that multer() returns an object that contains various functions that return different middleware, depending on your needs.
For example, to accept a single file whose name is 'avatar':
var upload = multer({dest: './uploads/'});
router.post('/upload', upload.single('avatar'), function(req, res) {
console.log('success');
});

Resources