Express 4 Multer / req.body and res.json not defined - javascript

I'm trying to do a single image file + text fields upload with using Express 4.0 & multer 1.1.0. The image file itself correctly uploads to the right destination but I'm getting errors with the text field and response:
1) multer's req.body req.file objects are undefined if logged in console
2) res.json (and also res.send when tested) gets the error - TypeError: res.json is not a function at Object.handle)
multer is configured as follows using moment.js for dates, which is almost line-for-line from the multer Github documentation:
//standard express-generator server.js requires
//passport.js implementation
var multer = require('multer');
var storage = multer.diskStorage({
destination: function(req, file, cb){
cb(null, './public/photoUploads/' + moment().year() + moment().month());
},
filename: function(req, file, cb){
cb(null, req.user._id + moment().unix());
}
})
var upload = multer({storage:storage});
require('./app/routes.js')(app, passport); //passport login routes - will eventually move app.post into this file
app.post('/upload/photoData', upload.array('photo'), function(err, req, res) {
var title = req.body.title;
var description = req.body.description;
var photoURL = req.file.filename;
var jsonResponse = {
"title": title,
"description": description,
"photoURL": photoURL
}
console.log(jsonResponse);
res.json(jsonResponse);
});
And here is the client-side form
<form id="photo-data" method="post" action="/upload/photoData" enctype="multipart/form-data">
<div class="form-group">
<div class="modal-body">
<label for="image" class="control-label">Photo upload</label>
<input type="file" class="form-control" name="photo" id="photo-main">
<label for="caption" class="control-label">Title:</label>
<input type="text" class="form-control" name="title" id="photo-title">
<label for="long-text" class="control-label">Further description:</label>
<input type="text" class="form-control" name="description" id="message-text">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button id="submit-photo" type="submit" class="btn btn-primary">Upload</button>
</div>
</div>
</form>
What am I doing wrong?

The signature for error handlers in Express is (err, req, res, next) (4 parameters), but Express sees less 4 than parameters in your handler so it assumes you're adding a normal route handler. The problem is that the order of your route handler parameters is wrong, it should just be (req, res). That will fix your res.json() error.
For your file field, you're currently telling multer you're expecting multiple files, so in that case you will need to check req.files instead of req.file. If you used upload.single('photo') instead, you could use req.file.
As for the non-file fields, make sure they are in fact submitted to the server by checking the network request for the form submission with your browser's developer tools.

Related

req.files keeps returning undefined

req.files keeps returning undefined. I've tried connect-multiparty, body-parser, and express-fileupload. How do I make it work using express-fileupload and not multer?
here's my frontend:
<form action="/api/upload" method="post">
<label for="imgHere">file:</label>
<input type="file" id="imgHere" name="imgHere"><br><br>
<input type="submit">
</form>
I've checked using inspect element network tab, its sending the image just fine.
here's my backend:
const express = require("express");
const app = express();
const fileUpload = require("express-fileupload")
app.use(fileUpload())
app.post('/api/upload', function(req, res) {
console.log(req.files) // logs undefined
res.send("uploaded.")
});
app.listen(80, function()
{
console.log("Server loaded.")
});
How do I fix this?
You need to specify proper enctype as form attribute as well, like this:
<form action="/api/upload" method="post" enctype="multipart/form-data">
<label for="imgHere">file:</label>
<input type="file" id="imgHere" name="imgHere"><br><br>
<input type="submit">
</form>

Form is not submitting in node

I am trying to make a post request from a html form and cant figure out where im going wrong.
> <form action="/api" method="POST">
<label for="username">username or email address</label>
<input name="username" id="username" type="text">
<label for="password">password</label>
<input id="password"name="password" type="text">
<button >Log in</button>
</form>
here is my main javascript file for the html (not the server)
"use strict"
let options = {
headers:{
"Content-Type" : "application/json"
},
method: "POST",
}
// fetch("/api",options)
And here is my node js server
"use strict"
//Installing express
let express = require(`express`)
let app = express()
app.use(express.json())
//running the server
app.listen(3000,()=>{
console.log("server is running boi");
})
//Middleware to load the static content
app.use(express.static(`public`))
//Database stuff
let Datastore = require('nedb')
let db = new Datastore({ filename: 'database.db' });
db.loadDatabase()
db.insert({username:"sid", password:"westham"})
//Handler for any post requests made
app.post(`/api`,(req,res)=>{
console.log("request was made");
console.log(req.body);
})
Two Observations
No middleware found in your server.js file for handling form data,
use body-parser http://expressjs.com/en/resources/middleware/body-parser.html
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true });
In your html form, if you're not submitting form with JavaScript then mentiod button type as submit
<button type="submit" >Log in</button>

Upload image to MongoDB with Nodejs and express

I'm trying to upload a image using multer in nodejs. I configured multer to save uploaded images in the "upload" directory and when the form is submitted, the image is sent to the directory as it should. But I'm trying to save the path to that image (req.file.path) to a mongodb database and this is not working. I'm new to nodejs and mongodb and I can't figure out what the problem is.
This is the error I get:
ObjectParameterError: Parameter "obj" to Document() must be an object, got assets\uploads\uploaded_file-1518264794720.jpg
at new ObjectParameterError (C:\xampp\htdocs\projets\NodeApp01\node_modules\mongoose\lib\error\objectParameter.js:23:11)
at model.Document (C:\xampp\htdocs\projets\NodeApp01\node_modules\mongoose\lib\document.js:55:11)
at model.Model (C:\xampp\htdocs\projets\NodeApp01\node_modules\mongoose\lib\model.js:59:12)
at new model (C:\xampp\htdocs\projets\NodeApp01\node_modules\mongoose\lib\model.js:3750:13)
Here is my index.js:
var express=require('express');
var app=express();
var fs=require('fs');
var multer=require('multer');
app.set('view engine','ejs');
app.use(express.static('assets'));
var mongo=require('mongoose');
mongo.connect('mongodb://username:pass#database...');
var schema=new mongo.Schema({
item:String
});
var model1= mongo.model('todomod',schema);
var storage = multer.diskStorage({
destination: 'assets/uploads/',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now()+ '.jpg')
}
})
var upload = multer({ storage: storage });
app.get('/',function(request,response){
response.render('index.ejs');
});
app.get('/add_item',function(request,response){
response.render('add_item.ejs');
});
app.post('/add_item',upload.single('uploaded_file'),function(req,res){
console.log(req.body);
console.log(req.file);
model1(req.file.path).save(function(err,data){
if(err) throw err
res.json(data);
})
});
app.listen(80);
console.log('Application listening on port 80....');
And here is my view (.ejs) for the form:
<body>
<% include partials/navigation.ejs %>
<h1>Adding an item to the shop</h1>
<form id="theform" action="add_item" method="POST" enctype="multipart/form-data">
Name of item:<input type="text" name="item" class="thedata"><br>
<br>
Photo of item:<input type="file" name="uploaded_file" class="thefile">
<button type="submit">Add item</button>
</form>
</body>
The issue is you are passing uploaded file path instead of file object, You can do like this to save uploaded file path in mongodb:
let db_data = {
item : req.file.path
};
model1(db_data ).save(function(err,data){
if(err) throw err
res.json(data);
})

req.file is undefined (multer, node.js)

I've been trying to upload an image for a while now, but req.file is still undefined. Can someone see why?
this is my page. I am able to pick an image when I click the '+' glyphicon, but on the server side req.file is still empty.
EJS file
input[type="file"] and input[type="submit"] have css styles display: none
<form action="/profile/addProfilepicture" method="post" id="form" enctype="multipart/form-data">
<span id="upload" class="glyphicon glyphicon-plus-sign"></span>
<label for="profilePic"></label>
<input id=profilePic type='file' />
<input type="submit">
</form>
<img class="profileImg"
src="<%="images/pexels-photo-370799.jpeg"%>"
alt="fail">
Client JS file
When I click the '+'glyphicon it lets me pick an image. When I do this, this will trigger the form to submit and send a post request.
$("#upload").on('click',function() {
$("input[type='file']").click();
});
$('input[type="file"]').change(function (e) {
$("input[type='submit']").click()
});
server side JS
On the server side it stops at:
TypeError: Cannot read property 'filename' of undefined
at C:\Users\Tijl Declerck\Desktop\projects\digitalNomadApp\routes\profile.js:27:38
at Immediate._onImmediate (C:\Users\Tijl Declerck\Desktop\projects\digitalNomadApp\node_modules\multer\lib\make-middleware.js:53:37)
at runCallback (timers.js:793:20)
at tryOnImmediate (timers.js:751:5)
at processImmediate [as _immediateCallback] (timers.js:722:5)
The console.logs I tried gave me this: req.body returns an empty object and req.file returns undefined.
var express = require('express');
var router = express.Router();
var multer = require('multer');
var User = require('../models/Users');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/profilePics')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
var upload = multer({ storage: storage }).single('myImage');
router.post('/addProfilePicture', function (req, res) {
var profilePicUrl = '';
upload(req, res, function (err) {
if (err) {
// An error occurred when uploading
} else {
console.log(req.file);
profilePicUrl = req.file.filename;
User.update({username: req.user.username}, {'profilePic.uploaded': true, 'profilePic.link': profilePicUrl}, function(err, doc){
console.log('THIS IS DONE')
});
}
});
});
You have to provide a name to your file input and it should match the single method's name, this is from multer doc:
.single(fieldname)
Accept a single file with the name fieldname. The single file will be
stored in req.file.
This is not well documented but fieldname refers to input name attribute
EJS file
<input id='profilePic' name='myImage' type='file' />
Express
...
var upload = multer({ storage: storage }).single('myImage');
...

req.files is empty when trying to upload a file to server with node js

HTML:
<form action="/uploadpic" method="post" enctype="multipart/form-data">
<input type="file" data-clear-btn="true" name="image" id="new_pic" value="" placeholder="Choose File">
<input type="submit" value="Add" style="width:30%">
</form>
NodeJS:
app.post('/uploadpic', function(req,res) {
console.log(req.files);
console.log(req.body);});
I also use:
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded());
app.use(bodyParser.json())
app.use(express.bodyParser({uploadDir:'./uploads'}));
app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
in the console I get:
{}
{}
i dont seem to understand what could be the problem here.. thanks !
var fs = require('fs');
app.post('/uploadpic', function(req,res) {
//req.files contains array of files iterate and get it
//if it has only one. it is like object
//here is the code for object
if (req && req.files) {
var contentType = req.files.file.type;
var fname = req.files.file.name;
var image_path = req.files.file.path;
fs.readFile(image_path, function (err, data) {
var data = data; //this is your data use this
})
}
})
BodyParser doesn't include file uploads. You need to use something like multer or multiparty.
Also express (4.0+) doesn't come bundled with middleware anymore, so you'll need to use bodyparser for POST requests.

Categories