React.js + FastAPI - File Uploads from React Application to FastAPI endpoint

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in a previous video we've seen how to upload a file using an HTML form and send that file to our fast API server in order to save the file to the file system in this video we're going to go a step further we're going to add a single page application as our client and we're going to use react in this video and we're going to learn how we can send a file from the client-side application to our fast API server and then how we can save that data to the file system again on the server so in this video we're going to learn how to programmatically add a file to a form data object and programmatically send that to the server with a fetch request so let's get started and dive into the video what we're going to do is to begin with is create a react application and in order to set up the react project I'm going to use the create react app and we have a command here using npx now in order to do this or in order to execute this command you're going to need node.js installed on your computer if you have that you can go to the terminal and what I'm going to do is execute a command here and it's npx create react app and then the name of the application education that we want to create now I'm just going to create an application called file demo here that's going to be the name of this react application now that might take a little while to install while it's doing that let's remind ourselves of the setup we had before we have a fast API endpoint it's called create upload file that takes a post request and that has a parameter called fail upload and that is of the type of upload fail from Fast API and the upload file object is a convenience wrapper around Python's spilled temporary file object and this object has methods such as read which is an asynchronous method and it has an attribute called file name as well so you can access the name of the file that's been uploaded now this endpoint is just going to take an uploaded file and it's going to save it to the file system at the location that we specify there and that's going to save that onto the file system of the running fast API server so now that our react application is created it's here in the file demo directory and the goal of this video is to use react in order to upload a file from the client side and send that trail to the fast API endpoint which will then save the file to the file system so let's get started and we're going to dive into the source directory of this react application that contains a file called app.js and this contains a react component called app and this is the root component of the react application we're going to remove the boilerplate here notably the header tag just going to get rid of that and we're left with a div that has the class name of app and what we're going to do is within the source directory I'm going to create a new folder that's called components and this is going to store any additional components that you define in a react application you can call this directly anything you like but I'm going to call it components and then I'm going to create a new react component in this file here it's called failform.js now I know in this channel we focused more On Tools like htmx and alpine.js and these are much more lightweight tools that integrate better with Native HTML but what we're going to do in this video is obviously dive into react react is a component based library and you can define components by defining standard JavaScript functions such as this one which we'll call failform now this is going to be a react component and what a component returns is HTML like code which is called jsx and we can define a return statement and The Returned HTML needs to have a root element so let's add a root element here which is just going to be a div and I'm going to quickly add some more HTML to this react component let's define an H1 tag that has the text upload file and then underneath that we can define a form element now within the form we need an input and that's going to have the type of fail and we can close that tag off now this input is going to have a button underneath it so we'll Define a button as well and that's going to have the type of submit and let's make the text within that button just say upload so here we have the basic HTML for this react component that's going to have a form and it's going to have a single field within that form that defines a file that can be uploaded so this is our initial attempt at our react component in order to use that in other files we need to export it so we can write a statement here where we export default the file form function that we've defined and then we can import that within the app.js file so I'm going to remove this logo at the top here we don't need that and then just below this import here I'm going to import the file form and that's from the slash components and then the file form.js file so in order to use the file form we can just refer to it here within our app component and we can close off that tag like that so this is a custom react component that we have created and in order to render the HTML within that we are referring to it with this syntax in the app component and then that is going to load the HTML that's defined here in this return statement or rather the jsx code it's going to load that into the app wherever we've defined this code here and this is how react Works essentially it builds up a tree of components starting at the root component which is this particular component here called app so what we're going to do now is run the react development server and in order to do that I'm going to bring a terminal over to this page here and we are in the file uploads directory that contains the main.pi the fast API file what we're going to do is go into the file demo directory which contains our react application and we can run a command here called npm Run start and that's going to start up the react development server and we can find the start command within the package.json file of the react project so if we go to package.json there's a script block here and that contains a bunch of commands one of them is the start command which will run this command here and that's how we can start up a development server that we can then use to serve the react project so once that is completed what we can do is we can go to localhost 3000 so let's go to the browser now and you can see we have our page it contains the H1 tag then it contains the fail field and also the upload button I'm going to wrap the fail field in a div tag so that the upload button appears below that and I'm going to add some margin bottom to the file field so let's get back to a react component which is defined in fail formed dot GS and let's surround the input with a div and I'm going to add some styles to this Dev and to do that and react what we can do is we can use two quarterly braces here and we can refer to some CSS and camo case in our case we're going to refer to margin bottom and I'm going to set that equal to 20 pixels and we can close that div tag and move the input of type fail into the div and we can save that and go back to the page which will Auto reload and now we have the upload button on a new line and we're using the two correlate braces here and that's because we're referring to a JavaScript object with the inner breasts and that object has the CSS keys that we need for example margin Bottom now what we're going to do is when the user selects a file using this input we want to store that file within the state of the react component now in order to do that we are going to use what's called a hook that you can use in a react component and that hook is called use state if we go to the documentation you can see it's a react hook and it lets you add a state variable to your component and this is the way that it's used here we call the US state hook and provide some initial State and that us statehook returns two objects the first one is State itself and that will be whatever the value of the state is at the given time the second object is a set or function you can call that when you need to actually change the value of the state so let's go back to the vs code we're going to import your state from the react Library so import your state from react and then within the component we're going to define a fail and also a set file Setter function and that's going to be equal to the use State call and the initial state that we're going to provide to the hook is just the null state so what that means is that the fail variable will be set to null initially and then when we actually select a file here with this input element it's going to update the value using the setup but we need to actually hook that up and that's what we're going to do now so within this input here we're going to add an event listener and that's going to listen for the on change event and then we're going to call a function that we're going to Define in a second and we'll call that function and handle fail input change now you can see we're using the single curly braces here and that's referring to a function that we're going to Define above the return statement here within the component so let's define that function now it's called handle file input change and that's going to be equal to an arrow function that takes the event as its parameter and within the body of this function we're going to call the set file Setter function to set the state that we have and we're going to pass through that the event.target.fails and we're going to index in at element 0 here and as well as that I'm actually going to console.l log the event.target so we can see what's on that object in the browser so let's quickly go over what's happening here when we select a file using this input element this callback function is going to be triggered and what's going to happen within this callback function is we're going to set the file state to the event.target.files let's save this and go back to the page and we're going to see exactly what happens here I'm going to load up the browser console and let's select a fail here I'm going to select the Json sample now you can see that being output here we have the input of type fail that's the console log output and that comes from line 7 here we are outputting the target which is the HTML element that has actually triggered this particular callback function if we look at the target's files by looking at the dot fails attribute and refresh this page if I select a file for example dog2 you can see that that returns a fail list now importantly even though we've selected only one file this is returning a list it's called a file list and it contains each file that has been selected in our case just a single file and that's the dog.png file and that's why we're indexing in at element 0 here so we can select the file that has been uploaded rather than getting the entire list of files so let's remove the console.log statement and the effect of calling set file and passing the particular file that's been chosen by the user is that it's going to set this state here called file and it's going to set that equal to whatever's been chosen by the user now I'm going to add a little bit of code at the bottom just below this form element and I'm going to see what the fail is set to at a given time so let's go below this form element and the name of the variable in the state is called fill and if that exists what we're going to do is we're going to Output A P tag and within that b tag we can display the fail.name attribute to actually output the name of the file that has been chosen so let's go back to the browser and you can see that that has updated already we've chosen a file called dog2.png and the name of that file is appearing below the button and that's because we're referring to the state variable called file which is being set whenever we select a new file and if we change the file that's been selected for example by choosing the Json sample you can see that that automatically updates and that's because the state itself is being updated within the react component and the state lives here on line four it's the file and whenever the state is updated the components code will re-render and you'll see the updated name of that file appear on the browser so that's great but what we actually need to do is programmatically submit this form and have it submitted to our fast API endpoint so what we're going to do within the form element we're going to add another event listener and that's to listen for the unsubmit event and when that event occurs we're going to call a function called handle submit that's going to be our callback function so let's copy the name of that and again within the component we're going to define a function called handle submit and that again will take the event itself as a parameter and let's now Define the body of this function firstly we need to prevent the default action which is to try and send data to a server so we can call event dot prevent default in order to do that and what we're now going to do in this handle submit is build up a form data object that we can then send to fast API so what is Forum data I'm going to go back to the fast API documentation here on this page we have a section called what is form data I'm going to link this below the video but form data is essentially a special encode coding for data that is submitted in HTML forms to servers and it's different from Json there's more information in this technical details section below I'll link this below the video there's another page I'm going to link called javascript.info and that contains a section on form data but the important thing to know for this video is that Network methods such as fetch they can accept a form data object as a body and that body can then send the data to the server and we can then process that form data whatever it may be whether it contains files or just other bits of information we can process that on the back end and that's exactly what we're going to do in this video so what we're going to do now is just go back to a react component here and I'm going to Define a variable here called form data and we can instantiate a new form data object and this is an API that's available in JavaScript if we go to the Mozilla documentation you can see that the form data interface it provides a way to construct a set of key value pairs representing form fields and their values and again that data can be sent with fetch requests or using the XML HTTP request.send method basically an Ajax request so we're going to construct this form data object and pass key value appears to that in our case we only need to pass a single key value pair and that's for the fail that's been uploaded so let's go back to line 14 here and to the form data object that we've created there's an append method and the first parameter to that form data object is the name that we want to send to the server in our case we're going to send a name of file upload and that matches the name of the parameter that we have within the fast API function that is going to handle this request by calling this fail upload and setting its type to an upload file it's going to be able to find this object this file within the body of the request so we're going to set the name here to fail upload and of course the value that's going to be sent we want to make that the file itself and remember the fail is here it's stored in the react State and the value of this file state is is going to be changed here using the set file Setter method and that occurs whenever we change the file input from the browser so that's how that process works we're appending that fail then to the form data and what we're now going to do is try and submit this to the server so we're going to use a try block here and I'm going to define the API endpoint let's call it endpoint and set it to localhost 8000 slash upload file and that again matches what we have on the fast API server there we then need to send a fetch request to that endpoint and we can look at the response as well here so we're going to set a variable called response and we're going to await our fetch request to that endpoint now in order to await a fetch request we need to make this method async and we can do that using the async keyword here and that will allow us to use this syntax here and await the response now we want to send a post request so what we need to do to the fetch request is set some options here we can do that with our JavaScript object and one of the keys that that takes is a method we can set that equal to post in order to send a post request with this Fetch and the second thing we're going to set is the body of the post request in other words what data are we actually sending to the server and we're going to set that equal to the form data object that we've constructed up here on line 13 and 14. once we get the response we can check if the response status code was okay and in that case we know everything has been found so we can console.log something to the browser so file uploaded successfully and if we didn't get an okay response we can define an else block here and I'm going to console.error failed to upload file so that's the try block we can also catch any errors that occur when we try to upload this file and in the case of any errors we can just console.log them to the browser and we can see what went wrong in that process so this is our handle submit function here when we submit the form containing the file it's going to construct a form data object and as a key called fail upload and set that equal to the file that's been selected it we're then going to send a fetch request to our fast API server and that fetch request is a post request that contains as its body the form data object that contains the file that's been uploaded by the user so let's now see if this works before we do that I'm going to minimize all of these and we're going to look at the uploads directory this is the server directory that contains the uploaded files and fast API the endpoint that we've written here is going to write out the content of any file that's been uploaded to this directory now we can see at the moment the uploads directory has nothing in it so we're going to test out whether we can upload a file from a react application now so let's go back to the browser and we're going to go back to the application page let's choose a file to upload here and I'm going to choose the Json sample file and we can hit upload and you can see we're getting a connection refused error and that's because I've not actually started the uvicon server that's going to serve the fast API application so let's go back to vs code and I'm going to run the uvicon command and that's going to start this server and hopefully now this is going to be able to accept that particular upload of the file so let's go back to the page refresh the page and we're going to select the dog and see if that will work as you can see on the console we've got the message that the file was uploaded successfully so let's go to the terminal here or rather on the left hand side the uploads directory and you can see that the dog.png has been uploaded and it has appeared in this directory and remember this directory is on the server fast API has received the fail from a react application and it's then stored that on the server at that particular location that we specified in line 5 here of main.pi so all of the code that we wrote in the previous video is still working on the fast API site because we've constructed a form data object on the react side and we're adding the file to that form data and then using that form data as the body of the post request that's going to our fast API endpoint so let's now change this example and we can see how it works with multiple files run other than just a single fail so what we're going to do is go up to the top of the react component I'm going to change the state that we've got here on line four because we're going to be working with multiple files I'm going to call the name of the state variable files and the setter is going to be called set files and we're going to initially set that to an empty array in JavaScript now below that we have this function here that handles what happens when the fail input changes now we need to refer to the new name of the setter function which is set files and within the actual parameter to that we can get rid of the indexing and we can use the entire fail list here but we do need to convert it from a file list to a native JavaScript array we can do that with the array Dot from function that's a static function on the array object in JavaScript so let's quickly go over this the event.target here is the input of type file that you can see in the code on Line 39 here so that has a type of fail and the dot fails attribute on that refers to an object called a fail list it contains a list of all the files that have been selected so that's a file list it's not a normal JavaScript array to convert it from that file list to an array we use the array.form function and what we also need to do to the input element itself of type file we need to add the multiple attribute here and that will tell the input element that it can accept multiple files rather than just restricting it to one file and I'm going to remove this statement at the bottom that's listing out the file name and the last thing that we need to do is go up to this form data code here and what we're going to do is Loop over the files that are stored in the state of this react component and for each one of them we're going to append it to a key called fail uploads so let's write some code here we're going to Loop over each file that we have in the state and for each one of those files we're going to define a callback function and in the Callback function to the form data we're going to append to that key of file uploads each file that we have in this state so that's going to pack all of the files that we have in the state into a key called fail uploads we need to go to a fast API endpoint and we're going to change the name of this to file uploads and then we can bring back the for Loop that we had in the previous video where we see four fail uploads and fail uploads and we can then tab over this content here to read the file and then write its content to the file system and finally we can return the name of each file to the client here by using a list comprehension and saying F dot file name for f in file uploads so let's now test this out and see if it works we're going to go back to a react application here and we're going to choose three of these files before I hit upload I'm going to go back to the server and remove any files from this directory so we can see if each of these are uploaded and finally we can go back and click upload here and you can see we are getting an error here and let's go back to the server code and you can see the problem within the terminal below here the upload file object is not iterable now what I've done wrong here is we have a single upload file type here we need to actually tell fast API that this is a list of upload files instead so we can use the list type here in order to do that let's go back to the page and we can try submitting these three files again when we hit upload we get the message that the file has been uploaded successfully if we go back to our server here within the uploads directory you see all three files so this is now working perfectly we have our fast API function that is looping over each file that's been uploaded and saving that to the file system what we're going to do just to finish the video is go over what's going on within the react component so starting from the top we're setting some state within that component and the state variable is called files and we have a setup function called set files that we can then use to change that state and we're calling that Setter function to change the state within this handle file input change function and that function is what's called whenever the user selects a particular file or set of files from this input element and then when the form itself is submitted we have a handle submit function that's a callback function that's called and this is the function that constructs a form data object and sends our post request to our fast API server with that form data as the body and that's basically all we need to do to get something up and running with react and fast API the process is very similar for other Frameworks like vojs or svelte if you're interested in those types of videos just let me know in the comments but that's all for this video thank you for watching if you've enjoyed the video please like And subscribe to the channel and we'll see you in the next video
Info
Channel: BugBytes
Views: 7,468
Rating: undefined out of 5
Keywords:
Id: iM4Pz-9oyiE
Channel Id: undefined
Length: 22min 28sec (1348 seconds)
Published: Thu May 04 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.