Managing Files Upload & Download
coding

Managing Files Upload & Download

Let's take a look at how we can manage upload and download of files on front-end. HTML has a default element, the file type input, that allows the user to upload files from his disk. Unfortunately, we don't have much control on the aspect of the input, because like checkboxes, radiobuttons, selects, etc. those are elements rendered by the browser. What we can do (and usually is done), is hiding the input, showing a button instead, that on click triggers via js the click of the file input:

<style type="text/css">
#addFile { display: none;}
</style>
<input type="file" name="addFile" id="addFile" onchange="uploadFile(event)">"
<button onclick="uploadFileOnInput()">Upload File</button>
<script type="text/javascript">
function uploadFileOnInput() {
document.getElementById("addFile").click();
}
</script>

But how we can handle the file in js, let's say to send it to the back-end?

One way to do it is transforming the file into a base64 string.

Base64 Encoding

Base64 is and encoding system that can be used to transform files (that at the end of the day are bits) into a string: this string then can be stored wherever we want, and it can be later reverted back into a file, for example to let the user download the file:

let filePassed;
let fileBase64;
async function uploadFile(event) {
filePassed = event.target.files[0];
fileBase64 = await toBase64(filePassed);
}

What we do here is reading the first file uploaded on the input via event (you can upload multiple files) and call another function, which transform the file into a base64 string (this process is asynchronous, hence the async modifier on uploadFile()).

async function toBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
return reader;
})
}

FileReader is a default web API that is able to read a file (there are other methods that can be used instead of readAsDataUrl(), depending on the type of file uploaded on the input) and transforming it in a base64 string. At this point, we have our string stored in the global variable fileBase4. Last step is making the user download the file:

<button onclick="downloadFile()">Dowload File</button>
<script type="text/javascript">
function downloadFile() {
const downloadLink = document.createElement("a");
const fileName = filePassed.name;
downloadLink.href = fileBase64;
downloadLink.download = fileName;
downloadLink.click();
}
</script>

A "trick" often used in those cases is to just create an <a> link into the DOM, assigning the base64 string to it as href, and initializing the click. This way the user's browser is gonna download the file.