Uploading Files With Next.js Just Got Way Easier

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so let's say you want to add a file upload feature to your next.js app but what kind of file input will it be a DropZone image upload like this one or maybe it's a multi-file upload like this one maybe it uploads as soon as you drop the files how do you display the progress are the files big should you use multi-part upload to make it faster and more stable what about your infrastructure what are you gonna use to store your files will you add a CDN layer to Cache your files close to the user do you need to create a thumbnail version of each image what about access control do you need private files okay my point is adding file uploads to your app can get quite complicated but all of that just got a lot easier with Edge store let's say we want to add two types of files to our app one is for images like posts or profile pictures and these should be public the order is for user files and these should be protected files only the user who uploaded it and admin users should be able to access it so let's start with the image upload here we have a brand new next.js application this one is using the app router but it also works with the pages router so let's create a new API route for Edge store make sure you name it like this so that it catches all the requests Under The Edge store API now these file is where we will add the configuration for Edge store let's start by initiating The Edge door Builder and then let's create our router here's where we will configure our Edge store buckets let's name this one my public images and set it as an image bucket now you want to create the API Handler make sure you import it from slash app if you're using the app router or from the slash Pages if you're using the pages router now all we need to do is create the Handler and Export it for the get and post requests we also need to export the router type which will be used to create a typesafe client in our front end and this is basically all the server side configuration we need to start uploading public images now let's set up the client side first we'll create an edge store file inside a lib folder this needs to be a client file here we'll use the edge store router type that we exported from our API route file to create the context provider that we wrap our app in the use Edge store react hook then we can go to the root of our app and wrap it with the provider we just created now the only thing left to finish the setup is to go to the edge store dashboard create a new project copy the keys and paste it to our environment variables now we're ready let's try to actually upload something in my client component let's start by showing a file input on the screen now we want to access the file we selected so let's add a state for it inside the state every time the selected file changes we also want an upload button let me just style it a little bit with Tailwind and here is where we will add the functionality to upload the files to Edge store first let's grab the edge store client from the use Edge door hook to call the upload function of our Public Image bucket if we take a look at the response type here we have an URL and a thumbnail URL and that's because image buckets automatically creates a thumbnail version of the uploaded image if it is bigger than a certain size after the upload finishes you could run some API or server action here to save the data to your own database but for Simplicity let's just show the data on the screen for that we'll need another state for the URL and the thumbnail URL and we'll set both of them after the upload finishes and in rjsx we want to show here the URL and the thumbnail URL now if you go to our app select a file and click upload we get back both links the URL with the original image in the smaller version of the image and if we go to the projects dashboard and open the bucket we can also see the files here and you'll also notice that the thumbnail image is not counted as USB storage in your account okay great but what if we want to show a progress bar as well well we can also pass an on progress change to the upload function let's first create a state for the progress and let's set this state on the own progress change Handler now let's just create a very simple progress bar here just a rectangle with a border in another rectangle inside that will view according to the progress we cannot use Tailwind for the width here because it is a dynamic width so let's just use normal inline Styles another thing if we change the progress from 20 to 80 you'll see that the change is instant we don't want that this will be too choppy we want a smooth animation between states so let's make it animate between states with a 150 millisecond duration now if we change it again from 20 to 80 percent that looks much better now let's link it to the progress and actually upload a file here and there we have it awesome and by the way we don't need to do all of this from scratch every time I just did it to show the customization flexibility of the package but if we just go to the documentation there are simple components there that you can just copy to your code for example let's use this single image component after we run this command to install the required dependencies we can copy the component create a single image drop zone file and paste it here now we can go back to the docs go to the usage copy this part of the code and paste it to replace our input component now this looks much better we can see the image and also clear it and we can set a size limit in the drop zone as well now if we try to drop a file bigger than one megabyte it will show us a validation error but this is just front end validation and only for this specific input if you also want this validation in the server side and for the whole bucket you can add it in the bucket configuration like this now that we're already here there is one more configuration I want to do remember that our image can be of type post or profile how about we add this information to the file for this we'll need to require an input that will take a type that can be of profile or post by the way you need to have Zod installed for this now we want to use this input to set the path of the image this will make a path like this and this information will be saved as a metadata for the file that you can use for filtering or for the access control logic in case of protected files now if we take a look at where we are uploading the file we will see that we have an error here this is the magic of advanced typescript since we added the input in our bucket configuration we need to set it here you might notice a lot of similarities with the RPC in the implemented patterns yes trpc was a huge source of reference on building this package I'm so glad that Alex and the other contributors made such a great open source repo with so many things to learn from but yeah back to the code we'll make this uptight post and if we go to our app and upload a new image we can see in the dashboard that the type is correctly set in the image path OK that's it for the public images and by the way all this code is available in a public repo on GitHub feel free to check it out if you want now let's start with the protected files since we only want the owner and the admin users to be able to access the file we need to create a context that will have this user information for the create context function we want to get the user information from our authentication provider whether you are using next auth or clerk just search for how you can get the current user information from the server side to make it simple here we'll just return a hard-coded context now we need to add the context type to the edge store Builder by doing this we will also be required to add the create context function in the router now going back to our bucket configuration we want to set the path here so that we can add the owner to it this will create a path like this where this is the owner's user ID now we can start with our Access Control logic let's start by adding an R added root and for our first condition we want the user ID in the context to be the same as the owner in the path which will be this one two three we have here again everything here is typesafe as you can see here now for our second condition we want the user role in the context to be an admin we can also write it like this instead and there are also other operators that we can use and that's it all we need to do to ADD protected files to our app now let's create a different input for this bucket we can copy the multi-file Drop Zone component from the docs add it to our components and paste it here now let's copy the usage in the docs create a new page you can name it anything you want and let's paste the usage here now if you go to the page we can start uploading files and we can also see it in the dashboard inside our new bucket that we have protected files with that lock icon here but we actually want to see it in action right so let's do the same thing we did in the image drop zone and display the links on the screen for that we need a state for the urls this time it's a list because we can upload multiple files now let's add a URL to the state when the upload finishes and let's map this list into links so they show on the screen now if you upload a new file and click the link we can see it because we have the right permissions but if we go back to our code change the hard-coded context to another user go back to the app and refresh the page so that the create context runs again and then try to open the same image we'll see that we don't have access to it anymore and the best part this Access Control runs at the edge without running any database queries so you don't need to worry about bad performance for protected files okay that's it for protected files but since we're already here let's see what happens if I try to upload a large file of 700 megabyte you'll notice that edge store automatically splits the upload into a multi-part upload for large files this actually makes the upload faster and also more stable let me just turn off my internet here you can see here that one part upload failed and it is already automatically retrying that part all these retry logic it's already implemented into Edge store so you don't need to care about it now if I turn my internet back on they upload successfully recovers from the failed part without having to start the whole upload from scratch okay next thing what happens if I try to upload many files at the same time you can see here that only five files are being uploaded in parallel and the rest are being queued and automatically starting as soon as another finishes the limit for parallel uploads can also be changed we just need to go to where we are creating the provider and set this option to whatever value we want let's make it too so we can see the queue better and here we have it only two files uploading at a time okay another thing I want to show you guys have you noticed that sometimes in forms the file uploads the start as soon as you drop the file this actually makes the ux better because the user won't have to wait for the upload after he clicks the submit button but it also has a drawback that if the user uploads the files and then leaves the page without submitting the form you will end up with unused ghost files in your storage to address that we can go to where we are uploading the files and add an option to make it a temporary file which will make sure this files gets deleted after some time if it hasn't been confirmed and to confirm it all we need to do is to run the confirm upload function inside the submit Handler now if you go back to our app and upload some files we can see in the dashboard that these files are marked as temporary files and then if we go back and submit the form then go to our dashboard again the files are confirmed by the way if you're interested in using Edge store it is completely free to start no credit card needed and there is also a bonus storage for early users so make sure you don't miss out on that either and if you think this project deserves it consider giving a star on GitHub this would mean a lot to me I really want to make this a Community Driven project so if you have any feedback or suggestions feel free to join our Discord and share it there and yeah that will be it for the video I hope to see you in the next one
Info
Channel: Ravi - Perfect Base
Views: 45,017
Rating: undefined out of 5
Keywords: Ravi, Perfect Base, perfectbase, React, Next.js, Typescript, Typesafe, typesafe components, Web Development, JavaScript, Frontend Development, React Tutorial, User Interface, UI Components, Web Application, Zod, Edge Store, edgestore, React tips, Upload files in Next js, Next.js tips, Private files next js
Id: Acq9UEA2akU
Channel Id: undefined
Length: 12min 19sec (739 seconds)
Published: Sat Sep 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.