0

I met the problem that the req.body of my Node.js always got undefined or NULL.

I found many past post. Some mentioned about the need of post-method, the body-parser and the need of property name of the tag. But not working for me at all. All I've added in my code.

server.js

const port = "5411";
const express = require('express');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const bcrypt = require('bcrypt');
const app = express()

app.listen(port, function () {
  console.log("server is running on " + port);
});
app.use('/static', express.static("static"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

const db_con = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "mitac123",
  database: "human_resource"
});

db_con.connect(function (err) {
  if (err) throw err;
  console.log("DB Connected!");
});

app.get("/upload", function (req, res) {
  res.sendFile(__dirname + "/html/homework.html");
});

app.post("/upload", function (req, res) {
  let name = req.body.name;           //it's here that I use console.log that get NULL or undefined
  let username = req.body.username;
  let password = req.body.password;
  let gender = req.body.gender;
  let email = req.body.email;
  let question = req.body.securityQ;
  let answer = req.body.answer;
  DB_CreateOrUpdate(res, name, username, password, gender, email, question, answer);
})

function DB_CreateOrUpdate(res, name, username, password, gender, email, question, answer){
  saltRounds = 10;
  data = {
    realName: String(name), 
    username: String(username),
    password: bcrypt.hash(password, saltRounds),
    gender: gender,
    email: String(email),
    securityQ: question,
    answer: answer,
  }
  var sql_com = "INSERT INTO user_data SET ?"
  
  db_con.query(sql_com, data, function (err, result) {
    if (err) throw err;
    console.log("1 record inserted");
    console.log(result);
    return res.send("Add successful!");
  })
};


HTML file

<!DOCTYPE html>
<html lang="zh-Hant-TW">

<head>
    <meta charset="utf-8">
    <meta name="author" content="JustBelieveMe">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="../static/js/homework.js" type="text/javascript"></script>
    <script src="http://static.runoob.com/assets/jquery-validation-1.14.0/lib/jquery.js"></script>
    <script src="http://static.runoob.com/assets/jquery-validation-1.14.0/dist/jquery.validate.min.js"></script>
    <script src="https://static.runoob.com/assets/jquery-validation-1.14.0/dist/localization/messages_zh.js"></script>
    <link rel="stylesheet" href="../static/css/homework.css" type="text/css" />
</head>

<body>
    <header name="header" id="header">
        Account Register Page
    </header>
    <div name="basicData">
        <form name="sheet" id="sheet" ref="fileUpload" action="/upload" method="POST" enctype="multipart/form-data">
            <fieldset>
                <legend>基本資料</legend>
                <br>
                真實姓名:<input type="text" name="name" id="name">
                <br>
                使用者帳戶:
                <input type="text" name="username" id="username">
                <br>
                密碼:
                <input type="password" name="password" id="password">
                <br>
                請再輸入一次密碼:
                <input type="password" name="verifyPassword" id="verifyPassword">
                <br>
                性別:
                <select name="gender" id="gender">
                    <option value="0">男</option>
                    <option value="1">女</option>
                </select>
                <br>
                大頭貼:
                <input type="file" name="headShot" id="headShot" value="選擇檔案" accept="image/gif, image/jpeg, image/png">
                <img id="imgPreview" style="width: 200px;" src="#" />
                <br>
                Email:
                <input type="email" name="email" id="email">
                <br>
                安全問題:
                <select name="securityQ" id="securityQ">
                    <option value="0">最喜歡吃的食物?</option>
                    <option value="1">第一隻養的寵物名字?</option>
                    <option value="2">最常用的網路ID?</option>
                    <option value="3">就讀哪一所國中?</option>
                    <option value="4">幾歲時拿到第一台個人電腦?</option>
                </select>
                <br>
                安全問題答案:
                <input type="text" name="answer" id="answer">
            </fieldset>
            <div name="buttonArea" id="buttonArea">
                <input type="submit" class="buttonC" id="submit" value="送出">
                <input type="button" class="buttonC" id="clear_btn" value="清除">
                <input type="button" class="buttonC" value="填值">
            </div>

    </div>
    </form>
    <footer name="footer" id="footer">
        <div>
            copyright© 2020 JustBelieveMe All Rights Reserverd.
        </div>
    </footer>
</body>

</html>

By the way, I will got an error:

UnhandledPromiseRejectionWarning: Error: data and salt arguments required

but I think it is caused by the null value of the req.body that the hash doesn't work.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437

3 Answers3

0

Well try this out:

install multer npm i multer

var multer  = require('multer')
var upload = multer({ dest: 'uploads/' })


app.post('/upload', upload.single('headShot'), function (req, res, next) {
  console.log(req.file);
  console.log(req.body);
})
bill.gates
  • 14,145
  • 3
  • 19
  • 47
  • 2
    a explanation would be much appreciated – Yadu Aug 24 '20 at 08:47
  • I got a `MulterError: Unexpected field`. And I guess this is for the headshot upload, that part is okay for me but the req.body is a quite big problem. And If you hope I could post the whole error message. – JustBelieveMe Aug 24 '20 at 08:55
0

Also as i see you are trying to do database operation. Should'nt it be asyncronous? May affect your situation maybe.

app.post("/upload", async function (req, res) {
      // your code goes
      // then
      await yourAsyncDBOperationFunction(req.body);
});

Also dont forget to use bodyParser. If u use for example express, then use the bodyParser as a middleware in your script file (app.js/index.js/server.js)

Look this: https://github.com/expressjs/body-parser

dogukyilmaz
  • 585
  • 5
  • 11
  • I think it's not async problem c'ause the console.log of req.body before DB operation is empty object. And after I tried still not work. And about bodyParser I've used `app.use(bodyParser.json())` or is it wrong use? – JustBelieveMe Aug 25 '20 at 02:56
  • Actually it is correct usage. Don't forget to use this above your routes. Also i realized something, you are trying to hash password with bcrypt. It is also asyncronous operation. Create hashed password variable with bcrypt as async operation then create data object to send with completed bcrypt hashed password. – dogukyilmaz Aug 26 '20 at 10:05
  • Thx! But I would like to ask more. For this register account page case, Isn't it better to synchronous hash password? To ensure that later login action could work smoothly and faster create account. I think for a user if the account hasn't established yet, he can't do anything. Or any other idea? – JustBelieveMe Aug 28 '20 at 02:52
  • https://www.abeautifulsite.net/hashing-passwords-with-nodejs-and-bcrypt#:~:text=The%20asynchronous%20approach%20is%20recommended,you're%20concerned%20about%20performance. Please check the yellow highlighted area, hope it will answer your question. – dogukyilmaz Aug 28 '20 at 11:26
0

Finally, I found the way to solving it.

I use

const fileUpload = require('express-fileupload'); 

...
app.use(fileUpload());

And the problem solved.

I guess multer is likely and I tried again. Finally got the same answer.

const multer  = require('multer');
const upload = multer({ dest: 'uploads/' });

...
app.post("/upload", upload.single('headShot'), async function (req, res) {
...
}

So I am here offer another solution. Also thanks everyone here.

And could anyone tell me what difference between express-fileupload and multer ?