Upload and Store Images in MySQL using Node.Js, Express, Express-FileUpload & EJS Layouts
In this article, we will explore the Express-FileUpload NPM package by creating a super simple user profile card and integrate our card with a MySQL database to retain the record.
What you need:
To complete this project you will need a MySQL Database & Node installed. I usually use XAMPP for local development, but you can use whatever you wish as long as the database is MySQL of course.
Create a new project
To create a new project all you have to do is to create a new project folder, let’s call it “upload-files” and then run the following command below in Command line or PowerShell. Make sure that you CD to your project directory. To initialise a new project simply put the following command:
npm init
This will initialise a new project for you and it’s going to ask you a few questions about your project. The most important one is to give your package a name and then you can just keep pressing enter until the installation is over.
This will create a new package.json file for you.
Dependencies Installation
There are a few dependencies that we need to install to get started. Here is the list:
[x] express [x] express-ejs-layouts [x] mysql
Let’s do that by opening the terminal / powershell and install the dependencies by typing the following command:
npm i express express-ejs-layouts express-fileupload mysql
Now let’s install Nodemon which will help us restart the server every time we make a change. Note that Nodemon is a development dependency so we have to install it by adding the –save-dev flag.
npm i --save-dev nodemon
Your packages.json file should look similar to this:
{
"name": "nodejs-user-profile",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"ejs": "^3.1.6",
"express": "^4.17.1",
"express-ejs-layouts": "^2.5.0",
"express-fileupload": "^1.2.1",
"mysql": "^2.18.1"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
}
Project Structure
Let’s create the following folders and files, leaving node_modules, readme.md, package-lock and package-json as that should have been automatically generated by now.
You can structure your project the way you like. I am just going to keep it simple and add everything into our app.js file
📂 node_modules 📂 public 📂 css 📜 main.css 📜 main.scss 📂 img 🖼 default.jpg 📂 upload 📂 views 📂 layouts 📜 main.ejs 📜 index.ejs 📜 README.md ⚓ .env 🌍 app.js 📜 package-lock.json 📜 package-json
Let’s create our app.js file and each block of code will be explained with comments.
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const fileUpload = require('express-fileupload');
const mysql = require('mysql');
const app = express();
const port = process.env.PORT || 5000;
// default option
app.use(fileUpload());
// Static Files
app.use(express.static('public'));
app.use(express.static('upload'));
// Templating engine
app.use(expressLayouts);
app.set('layout', './layouts/main');
app.set('view engine', 'ejs');
// Templating Engine
// Connection Pool
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'userprofile'
});
// Our GET router for the homepage and a simple SELECT MySQL Query
// We also render the page by doing res.render
app.get('', (req, res) => {
connection.query('SELECT * FROM user WHERE id = "1"', (error, rows) => {
// Once done, release connection
if (error) throw error;
if (!error) {
res.render('index', { rows });
}
});
});
app.post('', (req, res) => {
let sampleFile;
let uploadPath;
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
// name of the input is sampleFile
sampleFile = req.files.sampleFile;
uploadPath = __dirname + '/upload/' + sampleFile.name;
console.log(sampleFile);
// Use mv() to place file on the server
sampleFile.mv(uploadPath, function (err) {
if (err) return res.status(500).send(err);
connection.query('UPDATE user SET profile_image = ? WHERE id ="1"', [sampleFile.name], (err, rows) => {
if (!err) {
res.redirect('/');
} else {
console.log(err);
}
});
// res.send('File uploaded!');
});
});
app.listen(port, () => console.log(`Listening on port ${port}`));In our Views -> Layouts folder we need to create our EJS template. The <%- body -%> is where our index.ejs page will render:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
<div class="wrapper">
<%- body -%>
</div>
</body>
</html>Now let’s create our index.hbs page, with our form and a loop to display the record from the database:
<form action="/" method="POST" encType="multipart/form-data">
<h3>Upload Profile Photo</h3>
<input type="file" name="sampleFile" accept="image/*" />
<input type="submit" class="btn btn-primary">
</form>
<div class="card">
<% for(var i=0; i < rows.length; i++) { %>
<img class="card__image" src="<%- rows[i].profile_image %>" loading="lazy" alt="User Profile">
<h1 class="card__title"><%- rows[i].name %></h1>
<div class="card__job"><%- rows[i].job_title %></div>
<p class="card__about">
<%- rows[i].description %>
</p>
<button type="button" class="btn btn-primary">View Profile</button>
<% } %>
</div>That’s it. The clean code is available on the GitHub link below with fewer explanation comments.
Demo Video Loop
Demo of uploading an image and saving the record to a MySQL Database:
Thank you for reading this article. Please consider subscribing to my YouTube Channel.
More Resources:
Support This Work
If you found this guide helpful, consider supporting me with a small donation. Your contribution helps me keep these tutorials up to date and create more quality content.
Scan to donate
Its says ejs layouts but it looks like it is using hbs?
For some reason, I had handlebars in packages.json, but it’s all EJS. Thanks for this, Frederick I’ve updated the article. I need to upload this to Github as well.
You’re awesome dude! Seriously!
Thanks, Jacques! I appreciate it! 👊😎
Thank you a lot, buddy! This is what I just needed! 😎💪
👊😎