πŸŽ„ Get 50% off from our JavaScript course for the holidays! πŸŽ„
How to Open Any File in Javascript with Progressbar

How to Open Any File in Javascript with Progressbar

Using an ASCII text art in your search bar

Ferenc Almasi β€’ 2022 June 24 β€’ πŸ“– 7 min read

To open a file in JavaScript, we need to use a file input, which will render a button from where we can choose files to upload:

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

<!-- In case you want to allow multiple files to be opened -->
<input type="file" id="file" multiple />

<!-- In case you want to restrict the extension -->
<input type="file" id="file" multiple  accept=".jpg, .jpeg, .png" />
List of extensions must be separated by a comma when using the accept attribute
Copied to clipboard!

Make sure you add an id attribute so we can reference this field later in JavaScript to read the contents of the file that we want to open.

Note that you can define additional attributes on the fileΒ input for opening multiple files at once, or restricting extensions by the multiple and accept attributes respectively.

This will render the open file dialog accordingly. Meaning if you don't define the multiple attribute, you won't be able to select multiple files. Likewise, if you define a list of extensions usingΒ accept, then only those files will be visible in the open file dialog.

Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
JavaScript Course

How to Read the Contents of a File

To read the contents of the opened file in JavaScript, we need to grab the file input and add a change event listener to it:

const fileSelector = document.getElementById('file')

fileSelector.addEventListener('change', event => {
    const files = event.target.files

    console.log(files)
})
Grabbing the files from the file selector
Copied to clipboard!

Inside the callback of the change event, we can read the file(s) by referencing event.target.files. This is a FileList object which contains the selected list of files (like an array of objects). Since we can reference multiple files, this will be a list, even if we only select one file. Hence if we need to read the first file, we still need to grab it by the first index (files[0]).

Logging the file to the console gives us some metadata about the file. The following properties are exposed for each file:

{
    lastModified: 1653390333008
    lastModifiedDate: Tue May 24 2022 13:05:33 GMT+0200 (Central European Summer Time) {}
    name: "file.png"
    size: 132963
    type: "image/png"
    webkitRelativePath: ""
}
Metadata available for each file, such as the name, type, or size
Copied to clipboard!

However, this does not give us the contents of the file. In order to read the file after opening it in JavaScript, we need to use the FileReader API. Inside the callback of the change event, create a new FileReader to read the file:

const reader = new FileReader()

reader.addEventListener('load', event => console.log(event.target.result))

// Files can be read with the readAs[ArrayBuffer|BinaryString|DataURL|Text] methods
reader.readAsArrayBuffer(files[0])
reader.readAsBinaryString(files[0])
reader.readAsDataURL(files[0])
reader.readAsText(files[0])
Copied to clipboard!

We need to add a load event listener for the file reader to know when the file has been read. We can reference the result using event.target.result. This will contain the contents of the file.

Make sure you add event listeners prior to reading the file.

As you can see, we have multiple ways to read files in JavaScript. Based on which one you choose, you will get different results. We can read files as:

So for example, if you are dealing with text files, you will want to use readAsText. If you are dealing with an image, you will likely want to use readAsDataURL. If you are dealing with other types of binary files, you may want to use readAsBinaryString.

If you use readAsDataURL and try to select an image, you should now get the following logged to the console:

data:image/png;base64,...

Which you can then use in various different ways (using an img tag, using CSS, using canvas) to display the image.


Show Progress of File Reading

To show the progress of reading a file, we need yet another event listener attached to the reader. This time, we need to use the progress event:

reader.addEventListener('progress', event => {
    console.log(event)
})
Copied to clipboard!

If you log the event from the callback to the console, this will return a ProgressEvent object that contains the total file size and the size that is currently loaded into memory. We can use these two numbers to get a percentage of how much of the file has been loaded. To do this, we can use the following equation:

percent = Math.round((event.loaded / event.total) * 100)
Copied to clipboard!

So now we know how much of the file has been loaded, in percentage. To add a loading bar too, we are going to use two different ASCII characters, one for the loading background (β–’), and one for the loaded (β–ˆ).

We want to display 10 of these bars, and based on the loading percentage, we want to replace the background with the loaded character. So we will have the following:

0%  -> 'β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’' // 10xβ–’
10% -> 'β–ˆβ–’β–’β–’β–’β–’β–’β–’β–’β–’'
20% -> 'β–ˆβ–ˆβ–’β–’β–’β–’β–’β–’β–’β–’'
// And so on
Copied to clipboard!

We can achieve this, by first creating an array with 10 elements, each containing the background. Then we want to use the loaded percentage to replace some of the elements inside the array. So if the percent is greater than 10, we want to replace the first element. If it's greater than 20, we want to replace the first two elements, and so on. And to finally get a single string, we can join the array together using join. This leaves us with the following:

const loadingBar = Array(10) // Create an empty array with 10 elements
    .fill('β–’') // Fill all the elements with the background
    .map((item, index) => Math.round(percent / 10) > index ? 'β–ˆ' : 'β–’') // Replace the background
    .join('') // Create a string from the array
Copied to clipboard!

To break it down, let's see what is happening step by step, and what will be the value of the array, based on the percentage of loaded content:

// First we start off with an array of 10 elements:
['β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’']

// If progress reaches 10%, we get the following:
['β–ˆ', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’']

// If progress reaches 20%, we get the following:
['β–ˆ', 'β–ˆ', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’', 'β–’']

// Everything is connected together into a single string:
'β–ˆβ–ˆβ–’β–’β–’β–’β–’β–’β–’β–’'
Copied to clipboard!

The very last thing is to add this to the search bar of the browser, which we can do so by assigning this to location.hash:

document.location.hash = `${loadingBar}(${percent}%)`
Copied to clipboard!

If you now open a large file and try to read it, you should get a progress bar displayed in your search bar showing the loading progress of the reading.

ASCII loading animation after opening file in JavaScript
The progress event updates the loading every time progress is made

The entire code fits into 20 lines of code. If you would like to grab it in one piece, you can do so below. Thank you for reading through, happy coding!

const fileSelector = document.getElementById('file')

fileSelector.addEventListener('change', event => {
    const files = event.target.files
    const reader = new FileReader()

    reader.addEventListener('progress', event => {
        const percent = Math.round((event.loaded / event.total) * 100)
        const loadingBar = Array(10)
            .fill('β–’')
            .map((item, index) => Math.round(percent / 10) > index ? 'β–ˆ' : 'β–’')
            .join('')

        document.location.hash = `${loadingBar}(${percent}%)`
    })

    reader.addEventListener('load', event => console.log(event.target.result))

    reader.readAsBinaryString(files[0])
})
Copied to clipboard!
Share on
  • twitter
  • facebook
JavaScript Course Dashboard

Tired of looking for tutorials?

You are not alone. Webtips has more than 400 tutorials which would take roughly 75 hours to read.

Check out our interactive course to master JavaScript in less time.

Learn More

Recommended

πŸŽ‰ Thank you for subscribing to our newsletter. x