4 years ago
5 mins readThis is the fourth series of the Building an Email Application using Node JS Express JS with Gmail and Nodemailer. You can check out the third series Here where we retrieved data from our HTML form to the Node JS server.
In this article series, we will look into how we can handle files sent from the client-side to our project Node JS backend application.
In other to handle files coming from the frontend, we need to install a package called multer
Multer is a Node.js middleware, which is responsible for handling multipart/form-data in a form, which is primarily used for uploading files.
Multer also has a rule, which is that multer will not process any form which is not multipart (multipart/form-data).
In other to make multer
work in our project we need to add an encryption attribute to our form tag like below.
<form
action="/send_email"
method="POST"
enctype="multipart/form-data"
style="max-width: 500px; margin: auto"
>
Ensure to update your form tag with the new attribute, after that, we need to create a new folder called attachments
in our project root directory
Your project structure and index.js
should look like this
To configure our project to use multer, we need to first install it using the command below
yarn add multer
Once it is installed, we need to configure it in our index.js
file.
diskStorage
Multer allows us to specify where we want to store the attachments coming from the frontend and also define their unique names through its method called diskStorage.
require multer
below where we required the express
js
// Import express into our project
const express = require("express");
// Import multer
const multer = require("multer");
...
Copy-paste the following code, below the body-parser.
// Multer file storage
const Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./attachments");
},
filename: function (req, file, callback) {
callback(null, `${file.fieldname}_${Date.now()}_${file.originalname}`);
},
});
multer.diskStorage
destination
This multer method allows us to set the destination of our attachment through a callback function, and as you can see we passed our attachment
folder as the second argument of the callback function, this is where the attachment of a mail will be store (example coming up).
filename
The second property we can set using the diskStorage
is the file name of the incoming attachment, we do this so that every attachment will have a unique file name, we concatenate the field name (from, input name=" attachment") with underscore _
and current date that the file is been attached in milliseconds with another underscore _
and finally the attachment original name.
That is super unique ๐
Let's proceed to write middleware to actually get the attachment from the request body.
// Middleware to get a single attachment
const attachmentUpload = multer({
storage: Storage,
}).single("attachment");
What we are doing here is that we are passing the attachment storage logic we created into the multer object and also telling multer that we are only targeting a single attachment with the .single("attachment")
.
Now that we have set up a middleware with multer
, which will help us retrieve attachments from the frontend form, let's proceed to apply it within our Post route.
Update the application post route with the following code
// Post route to handle retrieving data from HTML form to server
app.post("/send_email", (req, res) => {
if (error) {
console.log(err);
return res.send("Error uploading file");
} else {
const recipient = req.body.email;
const subject = req.body.subject;
const message = req.body.message;
const attachmentPath = req.file.path;
console.log("recipient:", recipient);
console.log("subject:", subject);
console.log("message:", message);
console.log("attachmentPath:", attachmentPath);
}
});
attachmentUpload
middleware function and extend (pass) the req
and res
parameter from the post route function to it. This will allow the middleware to have access to any file in the request body.attachmentUpload
also takes in a callback function which will check for any error while attachmentUpload
processes the files from the request body.if
any error occurs, we want to display the error in the terminal and send back a message which says Error uploading file
as a response (res
).A call-back function is any function that is been passed as an argument to another function, which will be executed (call-back) later in time (any point in time).
else
block which is executed if the previous statement is not satisfied. This implies that the else
statement block will only run if there is no error when the middleware is trying to upload any attachments from the HTML form to the "attachment" folder.Let's proceed to test our implementation so far.
Save your script and refresh your browser (if you're not using a live server) to get updated with our node script.
Fill the form inputs and attach any file of your choice as shown below ๐ and hit the send button.
If all goes well, your terminal should have the following output ๐
You should also notice that the attachment name has changed to the naming convention logic we created earlier ๐.
The fun part is, if you expand the attachment folder, you will see your attached file there ๐, thanks to multer, you can also check the folder directory in the file explorer.
You can check the complete code to this point from my GitHub gist Here โ
In the next article, we will be setting up the Nodemailer package in our project.
Let me know in the comment section if you have any difficulties.