Live Demo
You can see the live demo of the app right here
Get Started
In order to get started you need to install these dependencies which are listed below
npm init -y
npm i express
npm i multer
npm i nodemon
npm i sharp
npm i image-size
Now make the entry level file index.js
and start a simple express server on port 3000 like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
const express = require("express"); const app = express(); const PORT = process.env.PORT || 3000; app.get("/", (req, res) => { res.sendFile(__dirname + "/index.html"); }); app.listen(PORT, () => { console.log(`App is listening on Port ${PORT}`); }); |
Now we will load the index.html for our user so that it can interact with the application. Copy paste the code inside the index.html file
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<!DOCTYPE html> <html> <head> <title>Mp3 Pitch Changer Web App in Node and Express</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" /> </head> <body> <div class="container"> <br /><br /> <h1 class="text-center">Mp3 Pitch Changer</h1> <br /> <form action="/processimage" method="post" enctype="multipart/form-data"> <div class="form-group"> <input type="file" name="file" multiple required class="form-control" /> </div> Choose Format: <label class="radio-inline" ><input type="radio" name="format" value="png" checked />png</label > <label class="radio-inline" ><input type="radio" name="format" value="jpg" />jpg</label > <label class="radio-inline" ><input type="radio" name="format" value="webp" />webp</label > <div class="form-group"> <label for="width">Width</label> <input class="form-control" type="number" name="width" id=""> </div> <div class="form-group"> <label for="height">Height</label> <input class="form-control" type="number" name="height" id=""> </div> <div class="form-group"> <button class="btn btn-danger btn-block">Download Image</button> </div> </form> </div> </body> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> </html> |
Creating Uploads Folder Dynamically
Now we will create the folders dynamically where we will store the image +files which will be processed by sharp
and then it will be resized and converted to a image file
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const fs = require("fs"); var list = "" var dir = "public"; var subDirectory = "public/uploads"; if (!fs.existsSync(dir)) { fs.mkdirSync(dir); fs.mkdirSync(subDirectory); } |
Here for the very first time the node.js application loads it will check the condition if the folder public doesn’t exist then it will create this folder and also it will create the uploads folder inside the public folder as a subdirectory.
Setting Public Folder as Static
Now in this block of code we will set the public folder as static so that it can store the image files
1 |
app.use(express.static("public")); |
Loading the BodyParser Middleware
BodyParser middleware is very much necessary for this application as we will processing the form data which is submitted by the user inside the index.html file. So for that you need to copy paste the below code inside index.js
1 2 3 4 5 |
const bodyParser = require("body-parser"); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); |
Uploading Image Files to Server Using Multer
Now the comes the most important part of the application we need to first of all upload the images to the uploads folder before we can process them. So for this we will be using a famous library of node called multer to do this task. Copy paste this block of code to upload files inside node.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
const path = require("path"); const multer = require("multer"); var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, "public/uploads"); }, filename: function (req, file, cb) { cb( null, file.fieldname + "-" + Date.now() + path.extname(file.originalname) ); }, }); const imageFilter = function (req, file, cb) { if ( file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg" ) { cb(null, true); } else { cb(null, false); return cb(new Error("Only .png, .jpg and .jpeg format allowed!")); } }; var upload = multer({ storage: storage, fileFilter: imageFilter }); |
Resizing Image Files and Conversion Process
Now we will do the fun part of the application after we upload the images files on the server. We will make use of the sharp
library to resize and convert images from one format to another. We will get the format which is selected by the user inside the html form and also we will check if the user has provided the custom width and height of the image or not. If they have provided then we resize the image with that dimensions. If they don’t provide it inside the form then we will pass the default dimensions width and height of the image. We will get the dimensions of the image by image-size
package.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
app.post("/processimage", upload.single("file"), (req, res) => { format = req.body.format; width = parseInt(req.body.width); height = parseInt(req.body.height); console.log(width); console.log(height); if (isNaN(width) || isNaN(height)) { dimensions = imageSize(req.file.path); width = parseInt(dimensions.width); height = parseInt(dimensions.height); processImage(width, height, req, res); } else { processImage(width, height, req, res); } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function processImage(width, height, req, res) { outputFilePath = Date.now() + "output." + format; if (req.file) { sharp(req.file.path) .resize(width, height) .toFile(outputFilePath, (err, info) => { if (err) throw err; res.download(outputFilePath, (err) => { if (err) throw err; fs.unlinkSync(req.file.path); fs.unlinkSync(outputFilePath); }); }); } } |
Deploy to Heroku
Watch the youtube video given above for this task
DOWNLOAD SOURCE CODE