Upload image and read json with express js - javascript

Problem:
Trying to get json string but req.body in the post data handler returns undefined. Is it even possible to send json and file in one post request to the server?
Code:
Data sended to the server:
function saveFile(e) {
let info = {titleI: title.value, dirI: dir.value};
let xhr = new XMLHttpRequest();
let formData = new FormData();
let file = e;
formData.append("info", JSON.stringify(info));
formData.append("file", file);
xhr.onreadystatechange = state => { console.log(xhr.status); }
xhr.timeout = 5000;
xhr.open("POST", '/register');
xhr.send(formData);
}
The post data handler:
router.post("/", (req, res) => {
console.log(req.body.info)
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
let dirName = "a"
fs.mkdir("D:/node website/ipgrabber/files/"+dirName+"/", function(err) {
if (err) {
console.log(err)
}
})
fstream = fs.createWriteStream("D:/node website/ipgrabber/files/"+dirName+"/" + filename);
file.pipe(fstream);
fstream.on('close', function () {
res.redirect('back');
});
});
})
This is the main class:
var express = require('express')
var http = require('http')
const mongoose = require('mongoose')
const { json } = require('express')
var cookieParser = require('cookie-parser')
var app = express()
var server = http.createServer(app)
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}));
var busboy = require('connect-busboy');
app.use(busboy());
//error handler
mongoose.connect('mongodb://localhost:27017/grabber', {useNewUrlParser: true, useUnifiedTopology: true});
app.use(cookieParser())
app.set("view engine", "ejs")
app.set('views', __dirname+'/views/html/');
app.use("/js", express.static(__dirname + "/views/js"))
app.use("/css", express.static(__dirname + "/views/css"))
const registerRoute = require("./routes/register")
const grabberRoute = require("./routes/grabber")
app.use("/register", registerRoute)
app.use("/id", grabberRoute)
app.get("/", (req, res) => {
res.redirect("/register")
})
app.use(function (err, req, res, next) {
res.status(400).send("Error code: 2 <hr> This page is currently inaccessible! <br> <a href='/'>GO TO HOMEPAGE</a>")
console.log(err)
})
server.listen(80)
Project resources:
body-parser - 1.19.0
connect-busboy - 0.0.2
cookie-parser - 1.4.5
crypto-js 4.0.0
ejs 3.1.5
express 4.17.1
mongoose 5.11.19

By default, express can't manage to get multipart/form-data correctly.
You have to use a middleware to handle and parse this request.
I recommend to use multer.
In your case, you're using connect-busboy so the info should be handled like this:
req.busboy.on('field', function(key, value, keyTruncated, valueTruncated) {
console.log('your info is here', key, value);
});

Related

Sending data formData througt Javascript to Express API

So, when i handle a post request througt javascript, i send the data to the api, and i don't know how to log the data in the API.
What i tried
app.post("/register", (req,res) => {
res.render("register/register", {});
-> i tried to log it as req.query, req.params or req.body console.log(req.query)
})
JS code:
document.querySelector("#regForm").addEventListener('submit', e => {
e.preventDefault();
let username = document.querySelector("#username").value;
let formData = new FormData(document.querySelector("#regForm"));
console.log([...formData]);
let data = JSON.stringify([...formData]);
console.log(data)
const request = new XMLHttpRequest();
request.open("POST", '/register');
request.send(data);
})
Edit:
The full API code:
const express = require("express");
const path = require("path");
var bodyParser = require('body-parser')
const app = express();
const port = process.env.POST || "8080";
var jsonParser = bodyParser.json()
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.listen(port, () => {
console.log(`Running on port ${port}`);
})
// middleware & static files
app.use(express.static('public'));
app.use(express.json());
app.set("view engine", "ejs");
app.use(express.static(__dirname + '/src'));
app.get("/profile/:name", (req,res) => {
res.render("profile", {username:req.params.name});
})
app.get("/register", (req,res) => {
res.render("register/register", {});
})
app.post("/register", jsonParser, (req,res) => {
res.render("register/register", {});
console.log(req.body)
})
Answer to LakiMancic - The error:
error
And nothing works. Can you help me? Thanks!
Try to specify Content-Type of your XMLHttpRequest with
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
After request.open(...); and before request.send(...);
Update ( Full Code that worked for me ):
const express = require('express');
const app = express();
const port = 3000;
app.use(express.json());
app.use(express.urlencoded({
extended: true
}));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/main.html');
});
app.post("/register", (req,res) => {
console.log(req.body)
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
document.querySelector("#regForm").addEventListener('submit', e => {
e.preventDefault();
let username = document.querySelector("#username").value;
let formData = new FormData(document.querySelector("#regForm"));
console.log([...formData]);
let data = JSON.stringify([...formData]);
console.log(data)
const request = new XMLHttpRequest();
request.open("POST", '/register');
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
request.send(data);
})

Empty body Api rest express node js

I'm trying to make an API using express in nodejs.
This api should get a request with a photo and post that photo to firebase storage.
The main problem is that for some reason the body of the requests I send are empty.
This is the code for the server:
const express = require("express");
const morgan = require("morgan")
const cors = require('cors')
const app = express();
// Settings
app.set('port', process.env.PORT || 3000)
app.set('json spaces', 4)
// middleware
app.use(morgan("dev"))
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.use(cors({origin: "http://localhost:3001"}))
// routes
app.use(require("./routes/index"))
app.listen(app.get('port'), () => {
console.log("Server using port " + app.get('port'));
});
Routes
const { Router } = require('express')
const router = Router()
router.post('/postImage', async (req, res) => {
try {
const image = req.body
console.log(image) // Here I only get an epty object "{}"
return res.status(200).json(image)
}
catch(error) {
console.log(error)
return res.status(500).json({error})
}
})
module.exports = router
Client side
const postImage = async (image) => {
console.log(image) // Here I get the image data
const response = await fetch("http://localhost:3000/postImage", {
method: "POST",
body: {message: "image"}
})
const data = await response.json()
}
I've tried using body-parser but it seems to be deprecated
you have to send an image from the front end in formData.
const data = new FormData();
data.append('myFile', 'Image Upload');
In back end use multer to upload file to server.
first install multer by : npm i multer
const multer = require("multer");
//Configuration for Multer
const upload = multer({ dest: "public/files" });
app.post("/api/uploadFile", upload.single("myFile"), (req, res) => {
// Stuff to be added later
console.log(req.file);
});
Here is a proper Guide to upload file using multer express js

Getting a 502 Bad Gateway error when I try and require code from Node.js files

I am looking to start including my route files in my Node.js and express application. However, when I require the local route files into my server.js file, and try to run that on Nginx, I get a 502 Bad Gateway error.
The code that is giving me trouble is currently commented out. Any ideas on what might be causing this performance?
server.js
require('dotenv').config();
const express = require('express');
const bodyparser = require('body-parser');
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
// const oidc = require('./okta');
// const searchRouter = require('./routes/search');
// const inputRouter = require('./routes/input');
// const dataRouter = require('./routes/view-all');
const app = express();
app.use(express.static('public'));
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
res.sendFile(__dirname + '/views/index.html');
});
app.get('/page', function(req, res) {
res.render(__dirname + '/views/optishop.ejs');
});
const listener = app.listen(8080, function() {
console.log('Your app is listening on port ' + listener.address().port);
});
Edit: This is the file being required in the searchRouter declaration.
search.js
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const oidc = require('../okta');
const router = express.Router();
router.post('/search', oidc.ensureAuthenticated(), async (req, res) => {
await MongoClient.connect(
process.env.MONGODB_URI,
{ useUnifiedTopology: true },
async (err, client) => {
assert.equal(null, err);
const db = client.db('test');
const arr = req.body.item.trim().split(/; */gi);
const user = req.session.passport.user.userinfo.sub;
const cursor = await db
.collection('test')
.find({
user
})
.toArray();
const filteredCursor = cursor.filter(obj => {
return arr.includes(obj.item);
});
res.render('index', {
cursor: filteredCursor
});
// res.send(filteredCursor);
client.close();
}
);
});
module.exports = router;

Nodejs with multer not uploading files through postman tool

I just want to upload file in nodejs using multer. I am using postman to check whether file is doing upload or not. Everytime when I am trying to upload file through postman its showing me error. So below are the code what I have done so far.
my express.js file looks like this
/* ===================
Import Node Modules
=================== */
const express = require('express');
const app = express();
const router = express.Router();
const mongoose = require('mongoose');
const config = require('./database');
const path = require('path');
const appRoot = require('app-root-path') ;
const event = require('./routes/event.router');
const multer = require('multer');
const bodyParser = require('body-parser');
const cors = require('cors');
const port = process.env.PORT || 8080; // Allows heroku to set port
mongoose.Promise = global.Promise;
process.env.NODE_ENV = 'devlopment';
// Database Connection
mongoose.connect(config.uri, {
useMongoClient: true,
}, (err) => {
// Check if database was able to connect
if (err) {
console.log('Could NOT connect to database: ', err); // Return error message
} else {
console.log('Connected to ' + config.db); // Return success message
}
});
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(appRoot.path, 'dist')));
app.use('/event', event);
// Serve only the static files form the dist directory
app.get('*', (req, res) => {
res.sendFile(path.join(appRoot.path, 'dist/index.html'));
});
// Start Server: Listen on port 8080
app.listen(port, () => {
console.log('Listening on port ' + port + ' in ' + process.env.NODE_ENV + ' mode');
});
event.router.js looks like this
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
const Event = require('../../model/event.model');
var multer = require('multer');
var upload = multer({ dest: './public/uploads/img/',fileFilter:function(req,file,cb){
var ext = file.originalname.split('.').pop();
cb(null, file.fieldname + '-' + Date.now() + '.' + ext);
}
}).single('eventimage');
[![router.post('/', function(req, res, next) {
upload(req, res, function(err) {
console.log('file', req.file);
});
if( !req.file ) {
res.json({ success : false, message: 'You must provide event image!' });
}
else {
res.json({ success : true, message: req.file.eventimage });
}
});
Here is the screenshot for the postman
event.router.js
var express = require('express');
var multer = require('multer');
var route = express.Router();
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads/')
},
filename: function (req, file, cb) {
console.log(file);
let extArray = file.mimetype.split("/");
let extension = extArray[extArray.length - 1];
// cb(null, file.fieldname + '-' + Date.now() + '.' + extension);
cb(null, file.originalname + '-' + Date.now() + '.' + extension);
}
})
var upload = multer({ storage: storage }).single('avatar');
route.post('/', function (req, res) {
upload(req,res, function(err) {
if (err) {
res.send('error uploading file');
}
res.json({
success : true,
message : 'File uploaded!',
file : req.file
});
})
});
module.exports = route;
index.route.js
var fileUpload = require('../routes/fileUpload');
var express = require('express');
var route = express.Router();
route.use('/upload', fileUpload);
module.exports = route;
Now include this index.route.js in your index.js file/app.js file what ever name you have kept.
Don't forget to install all dependencies.
And when uploading image see the name given in .single(), in my case i have written avatar.
See the attachments how to browse your file and what is to be set in headers.

reading a file to use within an express route

I am trying to implement a search functionality for my app. I have an express route to get incoming search terms.
Here is the entirety of my router file:
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var searchutil = require('../utils/searchhandler');
router.use( bodyParser.json() );
router.use(bodyParser.urlencoded({
extended: true
}));
router.post('/api/search', (req, res, next) => {
var term = req.body.searchTerm;
console.log(term);
searchutil();
res.json({test: 'post received'});
});
module.exports = router;
And here is my searchhandler file which is being including in my router:
var fs = require('fs');
var findResults = function() {
var items = fs.readFile('./server/assets/items.json', 'utf8', (err, data) =>{
if (err) throw err;
console.log(JSON.parse(data));
return JSON.parse(data);
});
}
module.exports = findResults;
This is all working just fine and dandy. it basically just prints out the contents of './server/assets/items.json' on the server when a post request route of '/api/search' is hit. The question I had was about using the json file within my router file. Say my router file was:
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var fs = require('fs');
var items = fs.readFile('./server/assets/items.json', 'utf8', (err, data) =>{
if (err) throw err;
console.log(JSON.parse(data));
return JSON.parse(data);
});
router.use( bodyParser.json() );
router.use(bodyParser.urlencoded({
extended: true
}));
router.post('/api/search', (req, res, next) => {
var term = req.body.searchTerm;
console.log(term);
console.log(items);
res.json({test: 'post received'});
});
module.exports = router;
So now my router file is getting the file asset and trying to print it out within my router.post('/api/search', ...); function. The problem that occurs is that when it attempts to print it in that function items appears to be undefined, but the print from within the fs.readFile(); correctly logs the contents of the file. I think this is some sort of scope issue I am running into with JS, but I am not sure how to explain it to myself so I thought I'd ask it here why it is working one way, but not the other.
You should use a callback:
var getItems = function(cb) {
fs.readFile('./server/assets/items.json', 'utf8', (err, data) {
if (err) cb({error: err});
console.log(JSON.parse(data));
cb({items: JSON.parse(data)});
});
};
And then change the route to:
router.post('/api/search', (req, res, next) => {
var term = req.body.searchTerm;
console.log(term);
getItems(function (cb) {
if (!cb.error) {
console.log(cb.items);
res.json({test: 'post received'});
}
});
});

Categories