• About WordPress
    • WordPress.org
    • Documentation
    • Learn WordPress
    • Support
    • Feedback
Skip to content
May 27, 2026
  • Linkedin
  • Twitter
  • Facebook
  • Youtube

Daily CyberSecurity

Zero-hour alerts. Unmatched analysis.

Primary Menu
  • Home
  • CVE Watchtower
  • Cyber Criminals
  • Data Leak
  • Linux
  • Malware
  • Vulnerability
  • Submit Press Release
  • Vulnerability Report
Light/Dark Button
  • Home
  • Technique
  • File Upload for JS Applications
  • Technique

File Upload for JS Applications

Ddos August 22, 2022 16 minutes read
tech-cloud

On the internet today, file upload is an extremely used feature in modern web applications. On a daily basis, people exchange millions of files through the internet, moving files from one server to another. Developers have therefore created a variety of techniques to quickly add file upload functionalities. They use the already-made powerful JavaScript file upload API to make file upload easy and stressless.

Let’s understand what a file uploader is, what it looks like, its features, how it works, and lastly how to integrate a powerful JS file uploader API into our JS web application.

What Really is a File Uploader?

A JS file uploader is a GUI component that allows the uploading of one or more files to a web server. Through these file uploaders, you can upload different types of files, including pictures, documents, audio files, and videos.

A common feature of several websites and apps is the ability to upload files. File inputs included in HTML forms were previously used to do this. This solution, however, has various drawbacks and necessitates a lot more coding.  Javascript  File Uploaders are useful in this situation.

With a number of complex capabilities that HTML file uploaders lack, JS File Uploaders make uploading files extremely simple because they allow:

  • Drag and drop functionality
  • File Validation
  • Countless sources of uploads
  • Fast image processing and transformation speed

And many more…

Because of ready-made file uploaders like Filestack uploader, developers no longer have to write long lines of code to implement file uploading functionalities in their web application projects, instead, they integrate these already-made file uploaders using as little as two lines of code.

Now we know what a file uploader is, let’s learn what are the features of an Ideal File Uploader for your next Web App project.

Features of an Ideal File Uploader

1. Friendly User Interface: Every user wants to explore a website that allows them to do more with less input of their energy. They want an all-in-one solution to their problems. The ideal file uploader must have a beautiful and customizable UI that makes uploading from any source painless and intuitive. Here are some features of a user-friendly file uploader.

  • Preview feature: the user should have the option of previewing their files before uploading so they can be sure they picked the correct files.
  • Multiple Uploads: a user wants to have the ability to select multiple files at a time instead of going back and forth to upload several files.
  • Responsive interface: a file uploader should let the user use it consistently across all devices.
  • Fast upload: this is to ensure that a user’s file is uploaded as quickly as possible regardless of the size.

2. Different sources of file upload: By far the most common and easiest form of file upload is users uploading files from their device storage. But with the provision of cloud storage, we might need to integrate a wide range of options for users to upload their files. With a solid third-party file upload solution, you can connect to content directly from the sources where your users have it without the hassle or effort often involved. Examples of file sources across different platforms are:

  • Cloud storage: uploading from cloud storage like Google Drive, iCloud, Mega, Dropbox etc. as mentioned
  • Remote URL: uploading by copying and pasting a link into the dialogue box.
  • Social media accounts such as Facebook, Instagram etc.

Not every website needs this, but giving a user numerous options always makes a website more user-friendly.

3. Secured file uploads With the rise of cybercrime and stealing of digital information, it is worthy to take potential security risks into consideration. These include malware injection, hosting of illegal files, stealing of users’ data and so on. Hence, there’s a need to authenticate file upload forms. Here are some security practices that can help you secure files:

  • Make a list of allowed file types: This depends on the kind of business you are in and what files you need to collect. This list is to determine what types of files you’ll accept or reject. I’m sure that accepting executable files is a bad idea, because these kinds of files might be capable of executing commands and running malicious code.
  • Use of multiple anti-malware tools to scan uploaded files.
  • To avoid the occurrence of a service outage, set a maximum and minimum file size.
  • Setting up SSL encryption to secure the passage of data between the web server and the browser.

 4. Image Editing Within the Browser

Users might need to edit images to align with the design of the website or app. Well-designed file uploaders should provide this functionality that aids these kinds of manipulations inside the browser: crop, resize, rotate, and so on.

How To Integrate JS File Uploads Into Web Forms?

Custom JS File Uploader

Set up the Node.js server

We will make use of the inbuilt HTTP package to build up the backend server.

Let’s start by creating a new folder for the project.

mkdir myfileuploader

Then, we need to create an index.js file that would be the entry point of our backend server.

touch index.js

After this, write the code to start the HTTP server.

const http = require(‘http’);      // import http module
const server = http.createServer();     // create server

server.listen(5000, () => {
console.log(‘Server running on port 8080’) // listening on the port
})

In the above code, we have created an HTTP server, running on port 5000.

Building the Frontend

Next, we build up the client-side of our project. On our frontend, we will create a basic HTML file which will contain an input field and a submit button to upload our file when clicked. There would be a status text that would show the status of the file uploading process.

In vanilla JS, we use an event handler to perform an action on a button click.

<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>File Uploader</title>
</head>
<body>
<h2>File Upload Service</h2>
<input type=”file” id=”file”>
<button id=”upload”>Upload</button>
<small id=”status”></small>

<script>
const file = document.getElementById(‘file’);
const upload = document.getElementById(‘upload’);
const status = document.getElementById(‘status’);
upload.addEventListener(‘click’, () => {
console.log(‘clicked the upload button!’);
})
</script>
</body>
</html>

Users can select the file and upload it by clicking on the upload button.

To render this HTML file on calling the root route, we would need to interact with our backend. The easiest approach is by using the server.on(‘request’) method to listen to all network requests in a Node backend server.

server.on(‘request’, (req, res) => {

if(req.url === ‘/’ && req.method === ‘GET’) {
return res.end(fs.readFileSync(__dirname + ‘/index.html’))
}
})

Accessing the file content on the client-side

After starting our backend server, we need to be able to read the file on the client-side. To do so, we are going to use the FileReader object, which allows web applications to asynchronously access the contents of files (or raw data buffers) saved in the user’s computer.

The syntax to access a file on the client-side using the FileReader object is:

const fileReader = new FileReader(); // initialize the object
fileReader.readAsArrayBuffer(file); // read file as array buffer

Under the files array for the input, we have access to certain input files. Although we are just currently creating it to support single file uploads, we can eventually expand it to support multiple file uploads as well.

const selectFile = file.files[0];

FileReader gives us access to a couple of methods which gives us access to the files from the backend to the frontend.

  1. FileReader.readAsBinaryString() — read the file in raw binary data
  2. FileReader.readAsArrayBuffer() — read file as array buffer
  3. FileReader.readAsText() — If we know the type of the file to be a text, this method is useful
  4. FileReader.readAsDataURL() — read the file and send the result as a data URL

For our project, we will use the readAsArrayBuffer method to read the file in small chunks and stream it to the backend server.

To monitor the client-side reading of the file, FileReader provides some event listeners such as onload, onprogress etc.

Here we would like to split our files into bytes and send them to the backend server, and we will be using the onload  event handler, which will be initiated immediately after the reading of the file is completed.

We might have considered using the onprogress method to make the application a fully streamable file upload process. But the problem with the onprogress method is that it does not tell us about the newly read file chunk; instead, it tells us the data read up until now. So, we go with the onload method.

Once the file is completely read, we split it into small bytes and send it to the backend.

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>File Uploader</title>
</head>
<body>
<h2>File Upload Service</h2>
<input type=”file” id=”file”>
<button id=”upload”>Upload</button>
<small id=”status”></small>
<script>
const file = document.getElementById(‘file’);
const upload = document.getElementById(‘upload’);
const status = document.getElementById(status);
upload.addEventListener(‘click’, () => {
// set status to uploading
status.innerHTML = ‘uploading…’;
const fileReader = new FileReader();
fileReader.readAsArrayBuffer(file.files[0]);
fileReader.onload = (event) => {
console.log(‘Complete File read successfully!’)
}
});
</script>
</body>
</html>

We are using a <small>  HTML tag that displays uploading… as soon as we start uploading and changes to uploaded!!! Once the file is successfully uploaded to the backend.

Split and send the file in bytes to the backend

Sending the entire file at once is not a smart idea because file sizes can occasionally be huge. Some proxy servers such as Nginx might suspect it to be malicious because of the file’s huge size. Therefore, we will split this file into chunks of about 5000 bytes and send each one to the backend individually.

Once the file has been read, we may access its contents as an array buffer in the event.target.result field if we carefully examine the event argument.

This file’s array buffer will be divided into 5000-byte chunks by our program.

// file content
const content = event.target.result;
// fix chunk size
const CHUNK_SIZE = 5000;
// total chunks
const totalChunks = event.target.result.byteLength / CHUNK_SIZE;

// loop over each chunk
for (let chunk = 0; chunk < totalChunks + 1; chunk++) {
// prepare the chunk
let CHUNK = content.slice(chunk * CHUNK_SIZE, (chunk + 1) * CHUNK_SIZE)

// todo – send it to the backend
}

These chunks must now be sent to the backend. Our old friend fetch is here to hit the backend server.

To prevent the file from becoming corrupted, we must transmit the chunks to the backend in the correct order.

Because we don’t want to overwhelm the backend server with queries, the second thing to do is to use async await while uploading.

fileReader.onload = async (event) => {

const content = event.target.result;
const CHUNK_SIZE = 1000;
const totalChunks = event.target.result.byteLength / CHUNK_SIZE;

// generate a file name
const fileName = Math.random().toString(36).slice(-6) + file.files[0].name;

for (let chunk = 0; chunk < totalChunks + 1; chunk++) {
let CHUNK = content.slice(chunk * CHUNK_SIZE, (chunk + 1) * CHUNK_SIZE)

await fetch(‘/upload?fileName=’ + fileName, {
‘method’ : ‘POST’,
‘headers’ : {
‘content-type’ : “application/octet-stream”,
‘content-length’ : CHUNK.length,
},
‘body’: CHUNK
})
}
status.innerHTML = ‘uploaded!!!’;
}

In the code above, we added the file name as a query parameter, because we need to append the content to a file, and it has to be a unique identifier, and in our case that would be the file name.

The user might want to upload the file with the same file name so we have to ensure that the backend does its work as expected, therefore, need a unique identifier. And for that, we use this beautiful one-liner:

Math.random().toString(36).slice(-6)

We won’t send any custom header because most of the proxies such as Nginx or HAProxy might block it.

Collect the chunks and store them on the backend

Since we are done setting up the client-side, the next step is to await the arrival of the file chunks and store them on the server.

To get the file name from the query params of the request, we use the below piece of code.

const query = new URLSearchParams(req.url);
const fileName = query.get(‘/upload?fileName’);

So, our code looks like this:

server.on(‘request’, (req, res) => {

if(req.url === ‘/’ && req.method == ‘GET’) {
return res.end(fs.readFileSync(__dirname + ‘/index.html’))
}

if(req.url=== ‘/upload’ && req.method == ‘POST’) {
const query = new URLSearchParams(req.url);
const fileName = query.get(‘/upload?fileName’);

req.on(‘data’, chunk => {
fs.appendFileSync(fileName, chunk); // append to a file on the disk
})

return res.end(‘Yay! File is uploaded.’)
}
})

Uploading more than one file

With vanilla JS, we have so far created a stunning application for single file uploads. Our next objective is to add support for multiple file uploads to our current implementation.

We will get started now.

When we look at it carefully, we can see that the backend is clever enough to handle multiple file uploads as well because it only needs to do one thing: take a chunk and add it to the appropriate file name that was received in the request. No matter how many files are being uploaded from the front end, it is absolutely unaffected.

So, let’s take advantage of it and improve our application for it.

Modifying the file input is the first step in allowing multiple file selections on the user interface. It now accepts input as a single file by default. We use the multiple input option to accept multiple files:

<input type=”file” id=”files” multiple>

With this one line of code, we are ready to receive multiple files from our user input and also we changed the id of our input tag from file to file.

We now know that all input files can now be accessible from the files.files array. So, the next step is very simple: we will loop over the array of selected files, divide it into small bytes one by one, and send it to the backend server and store it there:

for(let fileIndex=0;fileIndex<files.files.length;fileIndex++) {
const file = files.files[fileIndex];

// divide the file into chunks and upload it to the backend
}

With for loop it makes it very simple to iterate over each file and upload it to the backend.

To monitor our file upload status, we keep a variable that gets updated when a file uploads.

So, our script looks like this:

const files = document.getElementById(‘files’);
const upload = document.getElementById(‘upload’);
const status = document.getElementById(‘status’);

upload.addEventListener(

‘click’, () => {

// set loading status
status.innerHTML =
‘uploading…’;
let fileUploaded = 0;

for (let fileIndex = 0; fileIndex < files.files.length; fileIndex++) {
const file = files.files[fileIndex];

const fileReader = new FileReader();

fileReader.readAsArrayBuffer(file);

fileReader.onload =

async (event) => {
const content = event.target.result;
const CHUNK_SIZE = 1000;
const totalChunks = event.target.result.byteLength / CHUNK_SIZE;

const fileName = Math.random().toString(36).slice(-6) + file.name;

for (let chunk = 0; chunk < totalChunks + 1; chunk++) {
let CHUNK = content.slice(chunk * CHUNK_SIZE, (chunk + 1) * CHUNK_SIZE)

await fetch(‘/upload?fileName=’ + fileName, {
‘method’: ‘POST’,
‘headers’: {
‘content-type’: “application/octet-stream”,
‘content-length’: CHUNK.length
},
‘body’: CHUNK
})
}
fileUploaded += 1;

status.innerHTML =

`file ${fileUploaded} of ${files.files.length} uploaded!!!`;
}
}

})

Looking at our code, you should notice that we have achieved multiple file uploads in parallel as well. Take a look at the network tab on your developer console, you will see that file chunks are being uploaded in parallel, but yes, files are themselves being uploaded serially.

We are not waiting for the previous file to upload completely, all the files are being uploaded individually. As our backend is stateless, this functionality is perfectly working.

In conclusion, we now know how to build a file upload service with pure JavaScript. Evidently, this is the most efficient approach, but it’s enough to give you a fair understanding of a lot of core concepts about file uploading.

Third-party File Uploader

Filestack comes with comprehensive yet very user-friendly documentation. This section will give you a basic understanding of how to get started with Filestack File Uploader.

  • Sign up for a Filestack account.

Filestack comes with a free plan to allow users to try their file uploader before buying. This free plan includes 1GB of storage, 500 uploads, 1 GB bandwidth, and 1000 transformations. The premium plans cost between $59 to $359 per month and include much more features.

  • Retrieve the API keys

After creating your Filestack account, navigate to the developer portal and obtain your secret and API key by creating an application there. You will get a unique secret and API key for each application you create. These keys will be helpful to authorize and authenticate any actions performed on your resources. Moreover, you can apply different settings to each application you create. It enables you to apply specific settings to different file uploaders.

  • Setup the File Picker

You can set up the frontend File Picker by including the JavaScript SDK UMD module in the head section of your code, as shown below.

<script src=”//static.filestackapi.com/filestack-js/3.x.x/filestack.min.js”> </script>

Then, configure the client using your API key:

const client = filestack.init( YOUR_API_KEY );
client.picker().open();

Following is an example HTML file that includes a minimal and the default File Picker.

 
<!DOCTYPE html>
<html>
<head>
<script src = “//static.filestackapi.com/filestack-js/3.x.x/filestack.min.js”> </script>
</head>
<body>
<script>
const client = filestack.init (API_KEY);

client.picker().open();

</script>
</body>
</html>

That’s it, and you have successfully integrated the FileStack file uploader into your web page. The above example will output a basic file uploader with the default settings. However, you can apply many options and configurations to the above setup.

Conclusion

As you can see, creating a file uploader from scratch can be really strenuous and time-consuming as compared to using a third-party library.

You can use any of these methods, depending on your need to integrate a file uploader in your next web application.

Share this article:

Facebook Post LinkedIn Telegram

No related posts.

Search

Translation

CVE WATCHTOWER
🚨

Receive alerts for vulnerabilities being exploited in the wild.

⚑

Get notified instantly when a Proof of Concept (PoC) exploit is published.

πŸ”

Access critical info on vulnerabilities even when marked as "RESERVED".

🧠

Insights powered by decades of expertise and global intelligence sources.

🎯

Customize alerts with up to 10 keywords for your specific tech stack.

πŸ“Š

Export the raw CVE database for SIEM integration and reporting.

Upgrade Package

πŸ”΄ Live Critical Threats

  • CVE-2026-9642CVSS 9.8
    There is a mitigation bypass / (incomplete fix) for CVE-2025-62582 (Unauthenticated Remote...
  • CVE-2026-44451CVSS 9.3
    Lumiverse is a full-featured AI chat application. Prior to 0.9.7, the component...
  • CVE-2026-44450CVSS 9.9
    Lumiverse is a full-featured AI chat application. Prior to 0.9.7, the MCP...
  • CVE-2026-44449CVSS 9.1
    Lumiverse is a full-featured AI chat application. Prior to 0.9.7, when the...
  • CVE-2026-44444CVSS 9.1
    Lumiverse is a full-featured AI chat application. Prior to 0.9.7, the Spindle...
  • CVE-2026-48689CVSS 9.8
    FastNetMon Community Edition through 1.2.9 contains an off-by-one heap-based buffer overflow in...
  • CVE-2026-3660CVSS 9.8
    IBM Engineering Lifecycle Management 7.0.3, 7.1.0, and 7.2.0 could allow an unauthenticated...
  • CVE-2026-8633CVSS 9.8
    IBM Web Server Plug-ins for WebSphere Application Server and WebSphere Liberty 8.5,...
  • CVE-2026-46624CVSS 9.9
    Twenty is an open source CRM. From 1.7.7 through 1.16.7, a critical...
  • CVE-2026-44668CVSS 9.8
    FACTION is a PenTesting Report Generation and Collaboration Framework. Prior to 1.8.3,...
Powered by CVE WATCHTOWER

Recent Zero-Day Vulnerabilities

  • Exploited in the Wild: Critical OWA Spoofing Flaw (CVE-2026-42897) Hits On-Premises Exchange Servers
  • Exploited in the Wild: Maximum CVSS 10 SD-WAN Flaw (CVE-2026-20182) Grants Admin Control
  • Exploited in the Wild: Critical 9.8 CVSS RCE Hits Canon GUARDIANWALL MailSuite
  • Exploit Code Released: Public PoC Dumps for Windows BitLocker Bypass and SYSTEM Elevation Zero-Days
  • Exploited in the Wild: “Dirty Frag” Linux Vulnerability Grants Instant Root Access
  • Under Active Attack: Ivanti EPMM Zero-Day Exploited in the Wild via Harvested Admin Credentials
Our Websites
  • Penetration Testing Tools
  • The Daily Information Technology
  • Daily CyberSecurity

    • About SecurityOnline.info
    • Advertise with us
    • Announcement
    • Contact
    • Contributor Register
    • Login
    • About SecurityOnline.info
    • Advertise on SecurityOnline.info
    • Contact Us

    When you purchase through links on our site, we may earn an affiliate commission. Here’s how it works

    • Disclaimer
    • Privacy Policy
    • DMCA NOTICE
    • Linkedin
    • Twitter
    • Facebook
    • Youtube
    Copyright Daily CyberSecurity Β© All rights reserved.