In this tutorial we are going to see how you can upload files to a server using Node.js using JavaScript, which is very common. For example, you might want to upload an avatar, a thumbnail, a PDF file or any other image or file in various formats.
We are going to structure this tutorial in several parts. First we will create the project, then we will create the frontend code and finally the backend code for the server.
To understand this tutorial you will need some basic knowledge of the command line. If you have never used the command line before, see the following command line tutorial, which explains some basic commands for the most commonly used operating systems. You will also need to have both Node.js and the npm package manager installed.
Creating the project
The first thing we are going to do is to configure and create the project. To do this, create an empty directory somewhere, access it via the command line and use the following command to create the project:
npm init
We only need to install two packages. First install express using the following command:
npm install express
Next we will also need a middleware for express called express-fileupload which we can use to manage the files that are sent to the server:
npm install express-fileupload
Next, configure the file that will create the express server. To do this, edit the package.json file, which should contain the line "start": "node index.js" in the scripts section to tell Node which file to run when we start the application:
{
"name": "ulpload-file-ajax",
"description": "Tutorial in which an ajax medium file is created",
"version": "1.0.0",
"dependencies": {
"express": "4.16.2",
"express-fileupload": "^1.1.7-alpha.3",
"request": "^2.88.2"
},
"scripts": {
"start": "node index.js"
}
}
Next, we create the index.js file in the root folder of the project and we add the necessary code for the creation of a basic server:
const express = require('express');
const router = express.Router();const bodyParser = require('body-parser');
const fileupload = require('express-fileupload');
const FileController = require('./controllers/FileController');const app = express();
const fileController = new FileController();app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(fileupload());router.post('/ulpload-file', fileController.uploadFile);
router.use(function(req, res) {
res.status(404).json({
error: true,
message: 'Not Found'
});
});app.use('/api', router);
app.use(express.static(__dirname));
app.get('/', function (req, res) {
res.render('index.html');
});var port = 3000;
app.listen(port, function () {
console.log('Server', process.pid, 'listening on port', port);
});module.exports = app;
What we have done is to create the server. At the top of the file we have made a require of the express-fileupload
module, which is essential for uploading files.
We have included the FileController
class, located in the /controllers/FileController.js
file, although we haven't created it yet. In the uploadFile
function of this controller is where we will add the code in charge of uploading the file.
As for the path that will redirect the request to the controller, we have defined the path /api/upload-file
using the following function:
router.post('/upload-file', fileController.uploadFile);
We have added the /api
prefix to the path using the following statement:
app.use('/api', router);
Please have a look at this file, as we will be creating the frontend code next.
2. Frontend JavaScript code
In this section we will add the frontend code in charge of sending the file from the user's system to the server. To start, create the index.html
file in the root folder of the project. Next, edit the file you just created and copy and paste the following code, which we will explain later:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Ajax Node File Upload Tutorial</title>
</head>
<body>
<h1>Ajax Node File Upload Tutorial</h1>
<p><label>Select a new file!</label></p>
<input type="file" id="upload_file" />
<div id="result"></div>
<script type="text/javascript" src="resources/js/scripts.js"></script>
</body>
</html>
What we have done is to add a basic HTML5 template. We have also added an HTML input
field, which is the field that the user will interact with to upload the file:
<input type="file" id="upload_file" />
As you can see, we've linked to the /resources/js/scripts.js
script just before the closing </body>
tag. Let's add it, so first create the /resources/js
directory and then create and edit the scripts.js
file.
Now we are going to add the JavaScript code that will allow us to associate an event to the field we have created in order to upload the file to the server. First we will see the code and then we will explain it:
const uploadImage= event => {
const files = event.target.files;
const data = new FormData();
data.append('file', files[0]);
fetch('/api/upload-file', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(data => {
document.getElementById('result').innerHTML = 'The file ' + data.path + ' has been successfully uploaded.';
})
.catch(error => {
console.error(error);
});
}
document.querySelector('#upload_file').addEventListener('change', event => {
uploadImage(event);
});
In the last block of code we have registered a change
event for the input we use to upload the file. In this event we execute the function uploadImage
, which receives as parameter the click event itself, from where we will have access to the selected file.
What we do in the uploadImage
function is to get the selected file, located in the event.target.files
array. Then we create a FormData
object and assign the selected file to it. Finally we use the fetch function to send a POST
request to the /api/upload-file
path we created on the server.
Then we check if the file upload has been completed successfully, printing in the result
field the file path if it has been uploaded correctly, or displaying an error in the console otherwise. We return the path in the path
property.
3. Node.js Backend Code
Now let's take a look at the process that is followed on the server to upload the file. The first thing you need to do is create the /uploads
directory in the root folder of your project. This is the directory where we will upload the files.
We're going to create the /controllers/FileController.js
file as a controller. As before, we'll first look at the code for this file and then explain how it works:
class FileController
{
uploadFile = async (req, res, next) =>
{
const file = req.files.file;
const fileName = file.name;
const path = __dirname + '/../uploads/' + fileName;try {
file.mv(path, (error) => {
if (error) {
console.error(error);
res.writeHead(500, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify({ status: 'error', message: error }));
return;
}
return res.status(200).send({ status: 'success', path:'/uploads/' + fileName });
});
} catch (e) {
res.status(500).json({
error: true,
message: e.toString()
});
}
}
}module.exports = FileController;
We have created a class called FileController
as a controller, in which we have defined the uploadFile
function.
The first thing we do is to get the file we have sent, which should be in the variable req.files.file
, since file
was the name we have given it in the frontend code. Now we can get the name of the file, which will be in the variable file.name
.
Next, we have defined the path
where we are going to copy the file and then, using the function file.mv
, we copy the file to that path.
In case the file has been copied successfully, we will send the response back in JSON format:
return res.status(200).send({ status: 'success', path:'/uploads/' + fileName });
Otherwise, an error is returned.
4. Testing the app
Let's test the application to verify that everything works correctly. To do this, open a terminal window and go to the root folder of the project. Then run the following command to start the server:
npm start
Then go to the URL
http://localhost:3000/
and try uploading a file, such as an image in .png
or .jpg
format.
And that is all.
Top comments (0)