Uploading files is one of the most common features in a web application nowadays. There are a lot of JavaScript libraries available that handle the file upload like a breeze.

But let's not load a whole library just for this single feature that can be easily handled in native JavaScript using Fetch API. Fetch is a promise-based modern replacement of XHR for making HTTP requests in the browser.

Fetch File Upload

Let's add the following HTML input element to your website:

<input type="file" id="avatar">

Now add an event listener on the input that will be triggered when the user chooses a file:

// select file input
const input = document.getElementById('avatar');

// add event listener
input.addEventListener('change', () => {

Next, add uploadFile() method that receives a File object as input and uploads it on the server using fetch():

const uploadFile = (file) => {

    // add file to FormData object
    const fd = new FormData();
    fd.append('avatar', file);

    // send `POST` request
    fetch('/upload-avatar', {
        method: 'POST',
        body: fd
    .then(res => res.json())
    .then(json => console.log(json))
    .catch(err => console.error(err));

Do not set the Content-Type header for multi-part request with fetch(). The browser will automatically add the content type header including form boundary.

Validate File Type & Size

You can also validate the properties (like file type and file size) of the file before starting uploading on the server:

const uploadFile = (file) => {

    // check file type
    if(!['image/jpeg', 'image/gif', 'image/png', 'image/svg+xml'].includes(file.type)) {
        console.log('Only images are allowed.');

    // check file size (< 2MB)
    if(file.size > 2 * 1024 * 1024) {
        console.log('File must be less than 2MB.');

    // ...

Handling File Upload on Server Side using Node.js

Here is a example code that handles the above file upload request in Node.js. I am using express-fileupload — a simple Express middleware for uploading files. It parses multipart/form-data requests, extracts the files if available, and make them available under req.files property:

app.post('/upload-avatar', async (req, res) => {
    try {
        if(!req.files) {
                status: false,
                message: 'No file uploaded'
        } else {
            //Use the name of the input field (i.e. "avatar") to retrieve the uploaded file
            let avatar = req.files.avatar;
            //Use the mv() method to place the file in upload directory (i.e. "uploads")
            avatar.mv('./uploads/' + avatar.name);

            //send response
                status: true,
                message: 'File is uploaded',
                data: {
                    name: avatar.name,
                    mimetype: avatar.mimetype,
                    size: avatar.size
    } catch (err) {

Check out Uploading Files in Node.js and Express guide to learn in detailed how to handle file uploads in Node.js.

Handling File Upload on Server Side using Spring Boot

If you are planning to use Spring Boot for back-end, here is an example code snippet that processes the above file upload request in Spring Boot:

public ResponseEntity<String> fileUpload(MultipartFile avatar) {
    try {

        // upload directory - change it to your own
        String UPLOAD_DIR = "/opt/uploads";

        // create a path from file name
        Path path = Paths.get(UPLOAD_DIR, avatar.getOriginalFilename());

        // save the file to `UPLOAD_DIR`
        // make sure you have permission to write
        Files.write(path, avatar.getBytes());
    catch (Exception ex) {
        return new ResponseEntity<>("Invalid file format!!", HttpStatus.BAD_REQUEST);

    return new ResponseEntity<>("File uploaded!!", HttpStatus.OK);

Check out Uploading Files in Spring Boot guide for handling single and multiple file uploads in a Spring Boot application.

✌️ Like this article? Follow @attacomsian on Twitter. You can also follow me on LinkedIn and DEV. Subscribe to RSS Feed.

👋 If you enjoy reading my articles and want to support me to continue creating free tutorials, ☕ Buy me a coffee (cost $5).