expressjs - how to require multer in another file - javascript

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.

Related

req.files giving NULL after ajax call, not correct file name [duplicate]

I'm attempting to get a simple file upload mechanism working with Express 4.0 but I keep getting undefined for req.files in the app.post body. Here is the relevant code:
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
//...
app.use(bodyParser({ uploadDir: path.join(__dirname, 'files'), keepExtensions: true }));
app.use(methodOverride());
//...
app.post('/fileupload', function (req, res) {
console.log(req.files);
res.send('ok');
});
.. and the accompanying Pug code:
form(name="uploader", action="/fileupload", method="post", enctype="multipart/form-data")
input(type="file", name="file", id="file")
input(type="submit", value="Upload")
Solution
Thanks to the response by mscdex below, I've switched to using busboy instead of bodyParser:
var fs = require('fs');
var busboy = require('connect-busboy');
//...
app.use(busboy());
//...
app.post('/fileupload', function(req, res) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
fstream = fs.createWriteStream(__dirname + '/files/' + filename);
file.pipe(fstream);
fstream.on('close', function () {
res.redirect('back');
});
});
});
The body-parser module only handles JSON and urlencoded form submissions, not multipart (which would be the case if you're uploading files).
For multipart, you'd need to use something like connect-busboy or multer or connect-multiparty (multiparty/formidable is what was originally used in the express bodyParser middleware). Also FWIW, I'm working on an even higher level layer on top of busboy called reformed. It comes with an Express middleware and can also be used separately.
Here is what i found googling around:
var fileupload = require("express-fileupload");
app.use(fileupload());
Which is pretty simple mechanism for uploads
app.post("/upload", function(req, res)
{
var file;
if(!req.files)
{
res.send("File was not found");
return;
}
file = req.files.FormFieldName; // here is the field name of the form
res.send("File Uploaded");
});
1) Make sure that your file is really sent from the client side. For example you can check it in Chrome Console:
screenshot
2) Here is the basic example of NodeJS backend:
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
app.use(fileUpload()); // Don't forget this line!
app.post('/upload', function(req, res) {
console.log(req.files);
res.send('UPLOADED!!!');
});
It looks like body-parser did support uploading files in Express 3, but support was dropped for Express 4 when it no longer included Connect as a dependency
After looking through some of the modules in mscdex's answer, I found that express-busboy was a far better alternative and the closest thing to a drop-in replacement. The only differences I noticed were in the properties of the uploaded file.
console.log(req.files) using body-parser (Express 3) output an object that looked like this:
{ file:
{ fieldName: 'file',
originalFilename: '360px-Cute_Monkey_cropped.jpg',
name: '360px-Cute_Monkey_cropped.jpg'
path: 'uploads/6323-16v7rc.jpg',
type: 'image/jpeg',
headers:
{ 'content-disposition': 'form-data; name="file"; filename="360px-Cute_Monkey_cropped.jpg"',
'content-type': 'image/jpeg' },
ws:
WriteStream { /* ... */ },
size: 48614 } }
compared to console.log(req.files) using express-busboy (Express 4):
{ file:
{ field: 'file',
filename: '360px-Cute_Monkey_cropped.jpg',
file: 'uploads/9749a8b6-f9cc-40a9-86f1-337a46e16e44/file/360px-Cute_Monkey_cropped.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
truncated: false
uuid: '9749a8b6-f9cc-40a9-86f1-337a46e16e44' } }
multer is a middleware which handles “multipart/form-data” and magically & makes the uploaded files and form data available to us in request as request.files and request.body.
installing multer :- npm install multer --save
in .html file:-
<form method="post" enctype="multipart/form-data" action="/upload">
<input type="hidden" name="msgtype" value="2"/>
<input type="file" name="avatar" />
<input type="submit" value="Upload" />
</form>
in .js file:-
var express = require('express');
var multer = require('multer');
var app = express();
var server = require('http').createServer(app);
var port = process.env.PORT || 3000;
var upload = multer({ dest: 'uploads/' });
app.use(function (req, res, next) {
console.log(req.files); // JSON Object
next();
});
server.listen(port, function () {
console.log('Server successfully running at:-', port);
});
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/file-upload.html');
})
app.post('/upload', upload.single('avatar'), function(req, res) {
console.log(req.files); // JSON Object
});
Hope this helps!
Please use below code
app.use(fileUpload());
Just to add to answers above, you can streamline the use of express-fileupload to just a single route that needs it, instead of adding it to the every route.
let fileupload = require("express-fileupload");
...
//Make sure to call fileUpload to get the true handler
app.post("/upload", fileupload(), function(req, res){
...
});
A package installation needs for this functionality, There are many of them but I personally prefer "express-fileupload". just install this by "npm i express-fileupload" command in the terminal and then use this in your root file
const fileUpload = require("express-fileupload");
app.use(fileUpload());
PROBLEM SOLVED !!!!!!!
Turns out the storage function DID NOT run even once.
because i had to include app.use(upload) as upload = multer({storage}).single('file');
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './storage')
},
filename: function (req, file, cb) {
console.log(file) // this didn't print anything out so i assumed it was never excuted
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({storage}).single('file');
I added multer as global middleware before methodOverride middleware,
and it worked in router.put as well.
const upload = multer({
storage: storage
}).single('featuredImage');
app.use(upload);
app.use(methodOverride(function (req, res) {
...
}));
With Formidable :
const formidable = require('formidable');
app.post('/api/upload', (req, res, next) => {
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
https://www.npmjs.com/package/formidable
You can use express-fileupload npm package to decode files like
const fileUpload = require('express-fileupload');
app.use(fileUpload({useTempFile: true}))
Note: I am using cloudinary to upload image
enter image description here
express-fileupload looks like the only middleware that still works these days.
With the same example, multer and connect-multiparty gives an undefined value of req.file or req.files, but express-fileupload works.
And there are a lot of questions and issues raised about the empty value of req.file/req.files.

How to upload files using multer in Node.js?

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

How to upload zip file and give permanent link to its contents in express js

I am a fresher on Javascript and Node JS. I am looking for the solution to upload a zip file which contains pictures only and give these pictures permanent link. For now I can upload a zip file and extract all pictures in it as below:
var express = require('express');
var router = express.Router();
var multer = require('multer');
var fs = require('fs');
var AdmZip = require('adm-zip');
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 }).any();
/* get home page. */
router.get('/', function (req, res) {
res.render('index', { title: 'express' });
});
router.post('/', upload, function (req, res) {
var zip = new AdmZip("./public/uploads/Camera Roll.zip");
zip.extractAllTo('public/uploads/', true);
res.send(req.files);
});
module.exports = router;
Once I upload a zip file I saved it in 'public/uploads/'. How can I get the path which save uploaded zip file because now I just identify it in my code (var zip = new AdmZip("./public/uploads/Camera Roll.zip");). Is there any variable to denote it? And once I unzip the file all pictures are in the folder 'public/uploads', does that mean I gave a permanent link to all pictures?
I've found. Just use req.file.path but need to use var upload = multer({ storage: storage }).single(filename) firstly;

multer file upload not working

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

Renaming an uploaded file using Multer doesn't work (Express.js)

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.

Categories

Resources