Send Files With HTML5's Form and Catching with Express.js Handlebars Templating

Rodrigo Figueroa
Geek Culture
Published in
7 min readJan 23, 2022

--

Hi this is a new post about Express.js and Handlebars, I want to cover a little about send files with default form way and fetch, thus reach the goal of send data and files with JS.

Structure of the directory

First of all, you need to create a directory whatever name you want to choose, I choose filesjs just to be easy.

Initiate Package JSON

Second, run this command to create our Package JSON and in this way start installing packages.

$ npm init -y

Install Expres.js and Express Handlebars

To install dependencies you need to run this command, i is for install and the dependencies are next

$ npm i express express-handlebars

Handlebars Structure

After that we need to create views directory, layouts directory and create our server.js file, if you do the same as I did you can have something like this:

Example Structure for Handlebars
Example Structure for Handlebars

Third we need to add home, 404, 500, sendFiles views to our project and the main layout or default layout.

Example views and layouts
Example views and layouts
Example default layout in this case main
Example default layout in this case main
Example Home view
Example Home view
Example 500 and 404 views
Example 500 and 404 views
Example sendFiles view
Example sendFiles view
<div class="container"><div class="row"><div class="col-5"><h2>Sending files </h2><form action="/api/sendfiles/{{ year }}/{{ month }}" method="POST" enctype="multipart/form-data"><div class="form-group"><label for="userName">User Name</label><input type="text" id="userName" name="userName" class="form-control" value="Flame Princess"></div><div class="form-group"><label for="userEmail">User Email</label><input type="email" id="userEmail" name="userEmail" class="form-control" value="flame_princess@adventuretime.org"></div><div class="form-group"><label for="userFile">Insert Just Images</label><input type="file" id="userFile" name="userFile" accept="image/*" ></div><button type="submit" class="btn btn-primary">Send Data</button></form></div></div></div>

If you see the examples above in the main layout, I added Bootstrap CDN to add a little style to the form view and in the sendFiles view I added all the inputs and labels of the common form behaves, pay attention that I added {{year}} and {{month}} to the URL because we will add some dynamic variables, and also I added the method and the enctype in this case is “multipart/form-data” to send files

Our Server

Well this is the great part I am trying to be concise and neat, first I have the express framework then the app and the express handlebars library, importing home, sendFiles, API and thankyou these are functions that receive two parameter request and response, but I divided in one JS file called handles.js in our lib directory to be clean and for JEST testings then I added the engine and setting to the view engine templating, second I added the views, third the post view in this case I added the library multiparty a good library to manage multipart/form-data (files) and you also need to install it:

$ npm i multiparty
Example Complete Server code
Example Complete Server code

The interesting part of the multiparty is that it parses all the information from the request and pass it in two parts the fields and the files (a perfect way to manage data), but we need to instantiate a new Form and use the parse method adding req, error, fields and files, finally I added the error’s Class if something happens and passing the req, res, fields and files to the sendFilesCommon function

Four, I finished with the 404, 500 and the listen method to start our server.

Handles.js file part, in this part is just the request and response for home, sendfiles, thank-you. The API have two functions to manage the files and fields from the request, but if you see closely you can see that the function needs req, res, fields and files that we shared before on the post method

Example handles Js file
Example handles Js file
exports.home = ( req, res ) => res.render( 'home' )
exports.sendFiles = ( req, res ) => res.render( 'sendfiles', {
year: '2022',
month: 'july'} )
exports.thankyou = ( req, res ) => res.render( 'thank-you' )
exports.api = {
sendFilesCommon: ( req, res, fields, files ) => {
console.log( 'Fields: ', fields )
console.log( 'Files ', files )
res.redirect( 303, '/thank-you')
},
sendFilesFetch: ( req, res, fields, files ) => {
console.log( 'fiels: ', fields )
console.log( 'files', files )
res.json({
success: true
})}}

Run Server

Example Home page
Example Home page
Example sending data with default form’s behave
Example sending data with default form’s behave

If we click on the send data button, we can see that it sends us to the thank-you page

Example thank-you page
Example thank-you page

If we check the console output, we can see all the data from the user

Example output server
Example output server

Fetch Part

We need to change a little our server and view, adding script part and just we need to specify the method and the body in this case the browser does all the work for us check that I didn’t specify the headers (multipart/form-data) and also I used the new FormData() Object and with this all is done!

Example adding script to the sendfiles view
Example adding script to the sendfiles view

In addition, a fetch API and adding the h2 to tell the client if the process is successfully or if we have an error :(

<div class="container">
<div class="row">
<div class="col-5">
<h2>Sending files </h2>
<form id="formFiles">
<div class="form-group">
<label for="userName">User Name</label>
<input type="text" id="userName" name="userName" class="form-control" value="Flame Princess">
</div>
<div class="form-group">
<label for="userEmail">User Email</label>
<input type="email" id="userEmail" name="userEmail" class="form-control" value="flame_princess@adventuretime.org">
</div>
<div class="form-group">
<label for="userFile">Insert Just Images</label>
<input type="file" id="userFile" name="userFile" accept="image/*" >
</div>
<button type="submit" class="btn btn-primary">Send Data</button></form>
<h2 id="fetch_data"></h2></div></div></div><script>
let form = document.querySelector( '#formFiles' ),
h2 = document.querySelector( '#fetch_data' )
form.addEventListener( 'submit', e => {
e.preventDefault()
fetch( '/api/sendfilesfetch/{{year}}/{{month}}', {
method: 'POST',
body: new FormData( form )
})
.then( raw => {
if( raw.status < 200 || raw.status >= 300 ){
console.log( `Error managing your data ${ new Error( raw.status ) }`
)}
return raw.json()
})
.then( data => {
console.log( data )
h2.textContent = 'Your data was uploaded'
})
.catch( err => {
console.log( new Error( err.message ) )
h2.textContent = 'there was a problem uploading your data :('
})
})
</script>

Run server again

Example send files with fetch
Example send files with fetch

Send files!

Example successful delivery of the files
Example successful delivery of the files

Cool! we send the files, and we receive a success true everything is cool, but we need to check the console again

Example output files sent by fetch
Example output files sent by fetch

COOL!!! We did it

Complete code of our server

const express     = require( 'express' ),
app = express(),port = process.env.PORT || 1024,{ engine } = require( 'express-handlebars' ),
{home, sendFiles, api, thankyou} = require( './lib/handles' ),
multiparty = require( 'multiparty' )
app.use( express.urlencoded({ extended: false }))
app.engine( 'handlebars', engine({defaultLayout: 'main'}))
app.set( 'view engine', 'handlebars' )
app.get( '', home )app.get( '/sendfiles', sendFiles )
app.get( '/thank-you', thankyou )
app.post( '/api/sendfiles/:year/:month', ( req, res ) => {const form = new multiparty.Form()form.parse( req, ( err, field, files ) => {if( err ) new Error( `Error Handling The POST ${ err.message }` )api.sendFilesCommon( req, res, field, files )})})
app.post( '/api/sendfilesfetch/:year/:month', ( req, res ) => {const form = new multiparty.Form()form.parse( req, ( err, field, files ) => {if( err ) new Error( `Error Handling The POST ${ err.message }` )api.sendFilesFetch( req, res, field, files )})})
app.use( ( req, res ) => res.status( 404 ).render( '404' ))
app.use( ( err, req, res, next ) => res.status( 500 ).render( '500' ))
app.listen( port, console.log( `http:127.0.0.1:${ port }` ))

Conclusion

In conclusion, sending data is really common these days and also sending files are really handy we are all exchanging data for instance uploading in our Drive or sending images on social media we are always uploading files that is why this small example can help you with your next Express.js and Handlebars project.

Sources

--

--

Rodrigo Figueroa
Geek Culture

I’m a Web Developer, fanatic of books and Smash Player.