Uploading Files

Suppose your birdspotters want to upload their own local databases of names and species. You decide to add this functionality to your client. The birdspotter might have a file that looks like this stored on their computer or mobile device:

{
"chickadee": 17,
"bobolink": 4,
"common loon": 1
}

You start a new HTML file to test this feature in isolation, starting with a file input:

html
preview

Try saving the JSON above to a local file and submitting it via this form. What happens when you click the upload button?

Nothing happens when you click the button. You need to add a click listener. But what exactly do you do in it?

html
js
preview

Browser-based JavaScript can't generally read files because it doesn't have access to the file system. However, when the viewer chooses a file through a form element, read permission is granted for just the chosen file. You use a FileReader to grab the contents:

html
js
preview

The file input has a property named files that stores the chosen files. Since multiple files may be chosen at a time if the attribute multiple is set to true, this property holds an array. You only want the first element.

Try assigning the result of readAsText to a variable and logging it. What value do you see?

The FileReader reads the file asynchronously. Instead of returning a promise, it uses an event-based callback mechanism:

html
js
preview

Try uploading the JSON file. Do you see it echoed in the console?

You have the JSON in your hands inside the load callback. That's the JSON that you want to send in a PATCH request to your web service. You add an uploadDatabase function that sets the method, adds the Content-Type header to declare the encoding, and appends the JSON body:

html
js
preview

Try testing that the endpoint succeeded in importing the database by clicking the reload button in this slightly enhanced version of the client:

html
css
js
preview

When you click the reload button, getAllSpecies is called. This function now wipes away the old cards, issues a request to the get-all endpoint, and then creates new cards based on the results.