I'm building a chat application using Node.js and Express, and I'm facing an issue with receiving req.body in the controller when sending a message that includes a file attachment. I have the necessary code in place, but for some reason, the request body is not being parsed correctly.
async function sent(e) {
try {
e.preventDefault();
const messageInput = document.getElementById("message-input");
const message = messageInput.value;
// ! trim() method to remove any leading or trailing whitespace from the message variable
const groupId = localStorage.getItem("groupId");
const fileInput = document.getElementById("file-input");
const attachment = fileInput.files[0];
console.log({ groupId, fileInput, attachment });
if (message.trim() === "" && !attachment) {
return;
}
// const context = {
// context: message,
// groupId: groupId,
// };
const formData = new FormData();
formData.append("context", message);
formData.append("groupId", groupId);
formData.append("attachment", attachment);
for (const [key, value] of formData.entries()) {
console.log(key, value);
}
console.log(JSON.stringify(formData));
const token = localStorage.getItem("token");
const response = await axios.post(`${API_URL}/sendMessage`, formData, {
headers: {
Authorization: token,
"Content-Type": "multipart/form-data",
},
});
socket.emit("sendMessage", () => {
console.log("FE: sent is getting emitted");
});
messageInput.value = "";
fileInput.value = "";
} catch (error) {
console.log({ FunctionSentFE: error });
}
}
<div class="input-container">
<form action="#" method="post" onsubmit="sent(event)" enctype="multipart/form-data">
<input type="text" id="message-input" name="input" placeholder="Type your message..." width="100%">
<label for="file-input">
<i class="fa fa-paperclip attachment-icon"></i>
</label>
<input type="file" id="file-input" name="attachment" style="display: none;">
<button id="send-button" type="submit">Send</button>
</form>
</div>
const { Op } = require("sequelize");
const multer = require("multer");
// ? M in the end of variables is for model
const MessageM = require("../models/messages");
const UserM = require("../models/users");
const { uploadToS3 } = require("../Services/s3services");
const sendMessage = async (req, res) => {
try {
console.log({ sendMessageBE: "sendMessageBE" });
const { context, groupId } = req.body;
console.log(req.body);
// ? getting the email from the middleware
const email = req.authUser.email;
const user = await UserM.findOne({ where: { email } });
if (!user) {
return res.status(404).json({ error: "User not found" });
}
let attachmentUrl;
if (req.file) {
// Uploading the file to S3
const file = req.file;
attachmentUrl = await uploadToS3(file.buffer, file.originalname);
}
const message = await MessageM.create({
UserId: user.id,
text: context || "",
GroupGroupId: groupId,
attachment: attachmentUrl, // Save the attachment URL in the database
});
res.status(201).json({ message });
} catch (error) {
console.error(error);
res
.status(500)
.json({ error: "An error occurred while sending the message" });
}
};
// ? Services: contain network calls, modifies controller folder
const AWS = require("aws-sdk");
const dotenv = require("dotenv");
const multer = require("multer");
dotenv.config();
const upload = multer().single("attachment");
async function uploadToS3(data, filename) {
try {
const BUCKET_NAME = process.env.BUCKET_NAME;
const IAM_USER_KEY = process.env.IAM_USER_KEY;
const IAM_USER_SECRET = process.env.IAM_USER_SECRET;
// ? AWS related settings in the following link
// https://youtu.be/ihZ6aHiOIWQ?list=PL4dunL3FOEk0XNSrauPcapBXdyojKlM9x&t=771
let s3bucket = new AWS.S3({
accessKeyId: IAM_USER_KEY,
secretAccessKey: IAM_USER_SECRET,
});
var params = {
Bucket: BUCKET_NAME,
Key: filename,
Body: data,
ACL: "public-read",
};
return new Promise((resolve, reject) => {
s3bucket.upload(params, (error, s3response) => {
if (error) {
console.log({ s3buckerError: error });
reject(error);
} else {
// console.log({ s3bucketSuccess: s3response });
resolve(s3response.Location);
}
});
});
} catch (error) {
console.log({ uploadToS3ControllerError: error });
}
}
module.exports = {
uploadToS3,
upload,
};
Here's what I have already checked and tried:
I have confirmed that the necessary middleware (e.g., express.json() or multer) is properly configured and registered in my backend.
I have included the Content-Type header as "multipart/form-data" in my Axios request from the frontend.
Despite these efforts, when I send the message with a file attachment, the req.body in the backend controller is empty or undefined. As a result, I cannot access the message context or other data.