Send an image to your backend with the fetch() function — JavaScript, React
Fetch is a JavaScript function that allows us to fetch things to and from our database.
This operation of sending and retrieving objects can take a significant amount of time, so it happens asynchronously.
That is, the interpreter makes the http request and continues on to execute the rest of the code before receiving a response.
Sometimes we might have to send information over to the database first, in order to retrieve our data.
And this information might include a product or user ids, tokens, page indexes and so on, which for the most part are just in plain text format…
But what to do if for some reason, you need to send over an image file to your backend?
During development of my final project at Flatiron school “Plantae” — a plant identifier and reference app in which a user takes pictures of plants to get details on possible matches — I found myself having to do just that, so today I want to share with you how I went about it in just a few steps.
And even if you are unfamiliar with the js fetch syntax or how it works, no worries! because in this article we will be taking it from the top on how to fetch just about anything.
Finally, we will see how to send that image via the body of our fetch request.
Before we begin, Let’s get a quick overview of the fetch() function in JavaScript.
The fetch function:
fetch(pathToResource)
That is the path to the resource or API we are making the request to.
in our example the path will be a url that points to plantae’s backend:
fetch("https://theplantaeapi.herokuapp.com/api/v1/id")
Next, we will get a response, which could be the data that we requested, or any errors that might have occurred.
In any case, our response will return what we call a promise.
And a Promise
is just an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
The resulting value of a promise will be a form of raw data that we then have to parse in a way, or fit into a format that we can work with, like the text, blob or json formats.
In our case we want to convert our image file into a blob so that we can then send it via an http request.
So let’s begin by creating a function to convert our file into readable data!
Below i am using an arrow function expression because it’s easier to work with this in React, but feel free to write a traditional function if you prefer.
setImagePath = e => {}
JavaScript has a FileReader() object that
“lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user’s computer, using File
or Blob
objects to specify the file or data to read.
File objects may be obtained from a FileList
object returned as a result of a user selecting files using the <input>
element, from a drag and drop operation's DataTransfer
object, or from the mozGetAsFile()
API on an HTMLCanvasElement
.” — Mozilla
We will use it to read our image file as data with:
setImagePath = e => {
let reader = new FileReader()}
Here we have created a new instance of FileReader().
Next we will call our reader’s readAsDataURL() method which reads the content of the specified Blob
has aresult
attribute that will contain a data:
URL representing the file's data.
setImagePath = e => {
let reader = new FileReader()
reader.readAsDataURL(e.target.files[0])}
Since I was uploading a single image file every time I hardcoded e.target.files[0].
We call the onload() function which is a handler for the loadend
event and save the result in state:
setImagePath = e => {
let reader = new FileReader()
reader.readAsDataURL(e.target.files[0])
reader.onload = () => {
this.setState({
queryImage: reader.result
})
}}
Now we are all set to send out our fetch request!
And to keep things functional let’s make a new method to send our fetch request:
postImage = () => { fetch("https://theplantaeapi.herokuapp.com/api/v1/id", { method: "POST",
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(this.state.queryImage)
})
.then(res => res.json())
.then(data => {
do stuff with data
})
})
}
Notice I am using the JSON.stringify() method which converts a JavaScript object or value into a string.
Now that we have a fetch function we can just call it back as we set our file path in state:
setImagePath = e => {
let reader = new FileReader()
reader.readAsDataURL(e.target.files[0])
reader.onload = () => {
this.setState({
queryImage: reader.result
},()=> this.postIdentification())
}}
And viola!
Your backend should be receiving a your image blob shortly!
I hope this helped, and if you have other ways of sending images for processing in your backend with fetch() I would love to learn about them so leave me a comment below or dm me! and remember to follow for more on promises and fetch()!