¡Hello world!
I'm making a upload xls functionality. So, I use multer module in order to archieve this. Nevertheless, when I tested in Postman return me errors:
Upload.js(controlller):
const multer = require('multer');
const express = require('express');
module.exports = {
upload(req, res){
multer.diskstorage({
destination: function(req, file, cb){
cb(null, _dirname + '/uploads')
},
filename: function(req, file, cb) {
cb(null, Date.now() + '-' + '.xlsx')
}
}).then(res => res.status(200).json({
message: "File upload succesfully",
})
).catch(error => res.status(401).send(error))
}
And there is the routes:
const express = require("express");
const router = express.Router();
const { func } = require('#hapi/joi');
const controller = require('../../v1/controllers/Upload');
module.exports = (router) => {
router.route('upload').post(controller.upload);
return router;
}
And this sreenshot correspond Postman test
Really, what I'm tryng to make is a Upload functionality that upload and import xls files. With no database involved. But I dont know what I'm doing wrong. So if anyone could help or give me some tips in order to fullfill this goal, I'd be really grateful for this help
Thanks!
I'm new to NodeJS and I tried this to post images through postman.
But I can't figure out where am I lacking?
The postman parameters :
NodeJS Code
Now to access these values in my NodeJS, I'm currently doing this :
var express = require('express');
var bodyParser = require('body-parser');
const router = express.Router();
router.use(bodyParser.json());
router.post('/postData/uploadStory', function(req, res) {
console.log(req.files);
console.log(req.body);
res.json("Hi");
})
How can I get access to the image and the key-value?
Also looked at express-fileupload node-module for doing this work for me.
Created a simple ejs with input name=foo type=file
tried to access it in the server.js file as console.log(req.files).
Didn't work.
Am I missing something? Please help. Thanks.
multer is best option to upload file in node.js
create separate folder for multer like multerHelper.js
const multer = require('multer');
let fs = require('fs-extra');
let storage = multer.diskStorage({
destination: function (req, file, cb) {
fs.mkdirsSync(__dirname + '/uploads/images'); // fs.mkdirsSync will create folders if it does not exist
cb(null, __dirname + '/uploads/images');
},
filename: function (req, file, cb) {
console.log(file);
cb(null, Date.now() + '-' + file.originalname);
}
})
let upload = multer({ storage: storage });
let createUserImage = upload.single('photo');
let multerHelper = {
createUserImage,
}
module.exports = multerHelper;
In your routes import multerhelper file
const multerHelper = require("../helpers/multer_helper");
router.post('/upload/:userid',multerHelper, function(req, res) {
console.log(req.files);
console.log(req.body);
res.json("Hi");
})
When I try to upload a file using a post method, the req.file given by multer is returned undefined.
Maybe it's not getting the correct input by name? I'm really in the dark here.
Thank you in advance for your help
//Front-end form
<form action="/dashboard" method="POST" id="newproduct-form" class="row" enctype='multipart/form-data'>
<input type="file" name="productImage" class="form-control-file" id="exampleInputFile">
</form>
//Backend
const mongoose = require('mongoose');
const multer = require('multer');
const path = require('path');
//Set Storage Engine
const storage = multer.diskStorage({
destination: './public/uploads/',
filename: function(req, file, cb){
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
//Init upload
const upload = multer({
storage: storage
}).single('productImage');
router.post('/dashboard', (req, res) => {
upload(req,res,(err) =>{
if(err) console.log(err);
console.log(req.file);
});
}
I figured it out. I was using jQuery ajax. By doing $(this).ajaxSubmit({ajax content}); instead of $.ajax({ajax content}) I managed to make it work.
I have a problem with my uploader. I think everything with code is right and still the file isnt created in uploads folder. Also when i try to console.log(req.files) i get an empty array. I try to make it locally
Here is the code:
const express = require("express"),
app = express(),
multer = require("multer"),
bodyParser=require("body-parser"),
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads/');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now() + '.' + mime.extension(file.mimetype));
}
});
var upload = multer({ storage : storage }).array('userPic');
app.post("/postFormAct", isLoggedIn, function(req, res){
upload(req,res,function(err) {
console.log(req.files);
});
});
Also there is my form:
<form method="post" action="/postFormAct" enctype="multipart/form-data">
<input type="text" name="user"><br>
<input type="text" name="email"><br>
<input type="file" name="userPic"><br>
<input type="submit" value="Submit">
</form>
I think you have an issue with your function level middleware, you have isLoggedIn, you have to chain the multer middleware upload right after like so :
// ...
var upload = multer({ storage : storage }).array('userPic');
app.post("/postFormAct", isLoggedIn, upload, function(req, res){
console.log(req.files)
});
Here's a full working example :
const app = require('express')()
const bodyParser = require('body-parser')
const multer = require('multer')
const morgan = require('morgan')
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads')
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now())
}
})
const upload = multer({
storage: storage
})
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(morgan('dev'))
isLoggedIn = (req, res, next) => {
console.log('check if user is logged in')
next()
}
app.post('/uploads', isLoggedIn, upload.array('images'), (req, res) => {
console.log(req.files);
return res.send(req.files);
})
app.listen(8000, () => {
console.log(`server is listenning on port 8000`)
})
You can find a test repository here
Also make sure that your destination dir exist.
Instead of var upload = multer({ storage : storage }).array('userPic');
use
var upload = multer({ storage : storage }).any('userPic');
.any()
Accepts all files that comes over the wire. An array of files will be stored in req.files.
I just discovered something about Express middleware with multer.
You need to pass an array as middleware if you have more than one function that needs to act as middleware.
So this:
app.post('/uploads', isLoggedIn, upload.array('images'), (req, res) => {
console.log(req.files);
return res.send(req.files);
})
should become this:
app.post('/uploads', [upload.array('images'), isLoggedIn], (req, res) => {
console.log(req.files);
return res.send(req.files);
})
Note: Also notice that the upload middleware needs to go first...I don't know why this happens but that's the only way it worked for me.
I'm just putting this out there if anyone needs help with this(even though the question is pretty old and has an accepted answer).
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.