How to upload files on the Web
How to upload and preview files on the web? I had a task where I needed to upload an image and display a thumbnail on the screen the other day. While working on file uploads on the web, I started to wonder what exactly a blob
format is, why we use FileReader
, and what binary data
means.
Blob as the File Format
An input tag for uploading files looks like this:
<input type="file" />
Here, the format of the file is blob
. A Blob object represents a file-like data object that can be read as text or binary data. You can convert it into a ReadableStream
and process the data using its methods.
Blob Methods
- Blob.arrayBuffer(): Returns a promise that resolves with the blob’s entire content as a binary
ArrayBuffer
. - Blob.slice(): Creates and returns a new Blob object containing a portion of the original blob's data, starting and ending at the specified byte range.
- Blob.stream(): Returns a
ReadableStream
to read the contents of the Blob. - Blob.text(): Returns a promise that resolves with the blob’s entire content as a UTF-8 text string.
Reference: Blob - Web API | MDN
Binary Data and Base64
The file format is blob
, and blob
can be read as binary data. Binary data consists of ones and zeros, and all data and files are essentially binary. When saving images, they are stored as bytes (binary). If you want to display this saved binary data image on the screen, you need to convert it to base64 format. You can use the btoa
method in JavaScript for this. The btoa
method creates a base64-encoded ASCII string from binary data, and atob()
can be used to decode the data back.
Reference: WindowOrWorkerGlobalScope.btoa() - Web APIs | MDN
FileReader
The FileReader
API allows you to read the content of blobs or files. A FileReader
object provides methods to read the content of files or blobs, making it possible to save them to your computer. You can obtain a File
object from an input
tag where users select files or from a DataTransfer
object after a drag-and-drop operation.
const reader = new FileReader();
reader.addEventListener('loadend', () => {
// reader.result contains the contents of the blob as a typed array
});
reader.readAsArrayBuffer(blob);
FileReader Event Handlers
- FileReader.onabort: Triggered when the reading operation is aborted.
- FileReader.onerror: Triggered when an error occurs during the reading process.
- FileReader.onload: Triggered when the reading operation is successfully completed.
- FileReader.onloadstart: Triggered when the reading process starts.
- FileReader.onloadend: Triggered when the reading process is finished.
- FileReader.onprogress: Triggered while reading the blob content.
Note: Since
FileReader
inherits from EventTarget, all events mentioned above can be listened to using addEventListener.
Displaying the User's Selected Image
The MDN document Using files from web applications provides an example using vanilla JavaScript. Since I’m working on a project with React Hooks, I wrote my own version of the code. I'm sure there’s a better way out there somewhere, but here’s my attempt!
import React, { useState } from 'react';
export default () => {
const [file, setFile] = useState(null);
const [url, setUrl] = useState("");
const handleChange = (e) => {
const selectedFile = e.target.files[0];
setFile(selectedFile);
const reader = new FileReader();
reader.onload = () => {
setUrl(reader.result);
};
reader.readAsDataURL(selectedFile);
};
return (
<div>
<input type="file" onChange={handleChange} />
<img file={file} src={url} />
</div>
);
};
In this example, I stored the selected file in a state variable and added a file
attribute to the image. Adding this attribute makes it possible to later fetch the image for uploading. I created a new FileReader
object and set up the onload
function. As we discussed earlier, the onload
event triggers when the reading operation is successfully completed. Once the file is successfully read, I set the URL. You can set this URL as the src
attribute of the image tag, which will display the image on the screen.
When the image file’s entire content is loaded, the img
element's src
attribute is set to the loaded image, displaying the image on the page.