Free Next.js Course: 14 / Upload Image

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so we're working through completing this ad house form and the next step right now is to be able to submit the image and upload it to cloudanary but to do that we need to basically accomplish two things the first thing is that cloudnary is by default it's not open so nobody can just upload images to your clattenery account you need to have a signature to be able to do that so we need to create code that generates a signature and we only want to allow authenticated users to generate that signature we're going to do that by creating a mutation on our back end that will basically return us a signature for authenticated users and then with the signature we can upload the actual image to cloudinary and as a response they'll give us um an hd a url to that image that we uploaded so that's what we're working on now we're on this page here the houses ad and we'll go into the code so we're actually going to start on the back end we're going to start by declaring the mutation to generate a signature so that will be done within schema and within image and we're going to uncomment all of the imports at the top of the file get rid of this export and the first thing we want to declare is what's called an object type and this is basically what's going to be returned as the result of a mutation so difference from mutation and query query you're just asking for data it's like a get request in restful routes or in http verbs mutation is more like a post or a put or even a delete it's sort of all those other ones are patch and in this case we're creating a signature so that's why it's um it's going to be a mutation and not a query so what are we returning from this so we'll declare an object type i don't know why it's adding this extra object type we'll clean it up later in a second so it's going to wrap itself around an image signature and image signature is going to have two fields in it so the way you declare a field is field and then we return sort of what type the field returns so this one's going to be a string and it's going to be a signature field so we'll declare it as a string here so we've got some squiggles we will fix that in a second next we're going to declare our second field so this will also have a field declared through this decorator and the type returned is an int that we've imported here from type graphql string you don't need to because it's available in in javascript by default so this is going to be a time stamp field and the typescript type is number okay so we've got these squiggles here and it says signature has no initializer and is not definitely assigned in the constructure in the constructor sorry so we're going to fix that by adding a bang between the the declaration of the property and the colon that just says like don't worry i'm going to declare this i'm going to take care of it all good so let's get rid of this extra import because i don't know why i added that and now it's time to declare a resolver and the resolver is where you declare all of the queries and the mutations in this case for anything to do with image so why don't we start with the export class image resolver so that's the class we need to wrap it in the resolver decorator so now we can go and we can declare the mutation within here so the mutation is going to be called create image signature and it is going to return an image resolver so this class that we declared up here and we'll fill in the body in a second but we have to add the different decorators so the first one is that it's a mutation and what is this mutation going to return it's also returning an image signature it's sort of weird you always have to basically give the graphql types and then give the things for typescript so you sort of have to type it twice which is a little weird but that's the way it works and we can add an extra decorator around here called authorized and that will basically ensure that um remember that auth function we created that will basically return true only if there's a user id from that it gets it from the context this will only sort of call our mutation if authorized returns true so this will only work for authorized or authenticated users in this case so inside of create image signature our goal is to return an object that has signature and timestamp and the first thing we need to declare is the timestamp so this is going to be a new date dot get time and we're gonna divide it by a thousand because it gives it to it in milliseconds by default we just want it in seconds so we're gonna do that but because you're dividing by a thousand that would give you a like a float with decimal places we don't want that so we're just gonna wrap a mouth math.round around this so that we have an actual integer in this timestamp field because that's what the return type wants so with the timestamp we can now use some cloudinary functionality to generate a signature so we do that by saying khan's signature is equal to so we have imported cloudinary up here and we're going to say cloudanary.utils.api [Music] sign request and sign request wants to receive the timestamp and in an object and then after the object it wants the secret now this is a server-side secret so you'll never have it available on your client in the browser that's why not just anyone can generate these signatures it has to happen on the server because it should be secret and protected so we're going to say process dot end dot cloud and airy secret like that okay with that saved we actually now have everything we need to just return the timestamp and the signature from here so it's not liking this why not [Music] i feel like it should be timestamp is a number what does math.round give us a number okay i feel like this is just some weird thing with vs code remember we can come into the console and we can run yarn tsc and we can do a check with like actual typescript and see if there's any issues and it will tell us if there are and there are um do do time stamp does not so i'm time stamp time stamp what am i doing wrong time stamp is a number object literal may only specify known properties and timestamp does not exist i bet you this is the dumbest thing t-i-m-e-s-t-a-m-p time stamp time stamp okay what the heck is going on return we want an image resolver image resolver has time stamp and timestamp does not exist in oh i am okay everyone watching the video is probably just going to leave this in it's all good so the the return type here is not image resolver which is it's the class that it's in that makes no sense it is image signature oh boy okay and uh one other thing i noticed just it thinks signature um [Music] right here isn't any so we could just say that it's going to be a string just so that it's uh it's hoppy and it lines up with the image signature stuff i'm sorry you have to suffer through through me doing this okay next up next up so we've got the back end built we're going to go to the browser and we're going to open up localhost 3000 api graphql why are we doing this i just want to make sure that the schema includes our mutation which it doesn't so one thing we needed to do is to go back into schema index and we need to import the image resolver and then add the image resolver to the list of resolvers for our graphql schema if we do that we can refresh this and now we have the mutation showing up which is great exactly what we wanted and the other cool thing is that by by reloading this page here it's also updated our generated schema.gql file which is great because we're going to generate some types based on this data when we write our mutation in the browser so we're going to pop over to the browser now and we're going to go into components house form okay and we're talking about what happens when you submit the form so on submit it calls handle create with all of the data so at this point right here is where we're going to basically call the mutation and and get that signature and timestamp back but in order to call a mutation we first have to declare it so we're actually going to come up here and we'll just make sure we import the things we need so for now we need this use mutation and gql and we'll declare our signature mutation so this is the definition of the mutation we want to send to the back end so this is mutation and we're going to give it a name create signature mutation then we're going to actually call the mutation so create image signature and we don't have to pass any arguments to this it doesn't take any but what it gives us back is the signature and the time stamp like this so with this in place we've declared this what we can actually do is hop back to the console just clear this out and we can run a command called yarn code gin so yarn code gen is running a script that was declared in package.json and it's it's sort of long it's uh it's calling apollo client code gen it's saying i want to generate times typescript as opposed to like flow or something else where is the schema.gql that one we just looked at and basically where to what pages to include what to exclude and where to put the generated files so create a new folder for us inside of component or inside of uh source called generated and right now it's generated types for our call to the mutation this is really cool because now the data we get back from the mutation and the variables that we send to the mutation they're all typed so this is exactly what we wanted so if we go back to the house form now we can import the crate signature mutation type that i already sort of set up here so now we're going to come down into our component and we have to basically declare the use mutation hook so that we're able to call this mutation that we um declare it up here so what we're going to do is we're going to call const it's going to return us something and we're going to call use mutation and we're going to pass in the mutation so this was um signature mutation like this um and between here sort of after use mutation we can put in um what is the the return type what's the typescript interface that we're going to get back from this mutation when called so that was the one we just imported and it's going to give us here basically a function to call when we want to call this mutation so create signature like that so with this function set up create signature we can hop into handle create and basically call it so you can if you want at this point you can comment this out or just get rid of this we're going to start replacing this the real code what should we do when we're actually creating a form and the first thing we wanted to do was um call that signature we just created so whenever you call a signature it gives you data back we can't call it data because we already have a variable called data so we're going to just tweak it and call it signature data and that's going to be an asynchronous call to create signature the mutation we just set up here and then what we're going to do is basically check to see if we got something back from the server so we'll just say if signature data and if this was done we can um basically take that data out and put it into individual variables like um const signature and timestamp are equal to something but why don't we just console.log this out so we can see what we're getting back for now before we go on and we just continue with the rest of this process so we're going to come here just refresh so we have the latest open up the brow the console like that we need to enter an address it doesn't really matter where so that we can add an image and we'll go into desktop houses the donkey two beds and we'll click save so what we got back here first of all in network we have our actual graphql call so we sent this this mutation to the server server gave us back the data so it has data create image signature and then the signature and the time stamp which is exactly what we wanted and we console log this out here as well so we have the signature and the timestamp so that's what we want to basically access at this point so we're going to say const signature and timestamp are equal to so it was signet oops signature data dot uh create image signature so that's what will give us the signature and the timestamp and it's sweet because it's all typed because we declared this the return type right here so at this point with the signature and data we can post the actual image to cloud and airy upload it there and cloudnary will give us a url back of like how to access that image and to do that we need to send it three pieces of information so we're going to call a function called upload image we're going to give it three things we're going to give it the image itself so data image which is a file list the first image in that file list we're going to give it the signature and the time stamp so this is obviously going to return something we'll get to that in a second why don't we just to go declare this function first so we know what it's going to return so we're going to go up here we could put this above the interface it doesn't really matter where so we're going to say it's an async function because we're going to post the data using fetch so promises upload image so it received an image of type file a signature of type string and a timestamp of type number and it's going to eventually return the data from that but we'll get to that in a second so first where are we going to post the data to we need a url so if you go to your browser and you go over to the cloudinary dashboard so just log in go to your dashboard once this loads log in okay so right up sort of in this area if you more you're going to get this uh api base url so you can copy sort of up to the name of your account the cloud name they call it so that v1 slash that's the beginning of the url make sure there's no spaces so what we're going to do is embed the cloud name now you don't have to do this you could just put in whatever the actual cloud name but we set this up in an environment variable so we can just pull it from there so next public cloudinary cloud name and then we're posting specifically to a path called slash upload so to be able to post the data we're going to first create some form data that will then use fetch to post up so we're going to say form data is equal to new form data which is a like a native javascript object in the browser to the form data we can append our information so we have a file which is type of image we have a signature which is type which is the value sorry of signature we have our timestamp and timestamp will be timestamp you can't send numbers through forms so you actually have to convert this to a string by calling tostring and then last we have to send up our api key because it's going to validate sorry our cloudinary key so our publicly available key it's going to basically compare that to the signature and make sure that it's a valid one that could be created so api key and that's process dot end dot next public cloudinary key keep typescript happy by uh by um doing the question question mark question mark empty string so that it it's for sure gonna get a string so with our form data set up we could space this out a little bit better we've got our url we've got our form data we just have to post it so we're going to use fetch for that so const response is a weight fetch we're going to send it to the url we set up above and we need to send some headers so the first one is that we're posting this data by default fetch does get requests and we need to give it the body of what we're posting so that would be the form data so from our response we get our json oops form data with a small f and we're just going to return this from our function so return response dot json and because it's asynchronous and we're returning a promise it's all good we'll basically just wait for it to resolve over here so come down to where we called this so at this point we need to put what it gives us into a variable so we're just going to say image data is equal to await the upload image so that will give us something back now i didn't declare a type for this so why don't we just take a look at what it's giving us back and then we can go and uh declare a type for that so we're just going to console.log this out image data okay so back to the browser over to our app just refresh it so we can um open up the console again 10 whatever street donkey number of beds send took a second no because think about all it's doing um it had to call our mutation to get a signature and then upload the image to cloudinary and get a response back from cloudanary but what cloudinary gave us is a whole bunch of information um an asset id a format jpeg the height of the image public id which is important but what we're actually going to use is this secure url so why don't we actually just copy this and paste it in a browser and there's our donkey image so this is our donkey image being served from cloudanary that we just uploaded public id is important because we're going to use it later to show these images but it's actually in the secure url so we can just like extract this out later so all we really care about is this secure url so what we're going to do is just come up here and we're going to declare an interface and we're going to call it uh let's say i upload image actually let's call it upload image response i've been putting i before all my interfaces just as a standard so we'll put that there so what is this going to give us back it's going to give us a secure url which will be a string now it has a whole bunch of other stuff but we don't care about it so that's all we're going to declare so we have to come here and we have to say it's going to return a promise and when the promise resolves it will be an i upload image response so now we can come down here and we could say something like const image url is equal to image data dot secure url so it has this available um for now we're just going to leave this out save it like this and we've accomplished what we want to in this video we now have to move on to creating a mutation to create a house so that's going to be our next bet but in order to do that we needed this image data that that secure url and we've got that done so we've accomplished our goal so the files that were changed in this video we added a new mutation that tweaked the schema we modified the house form to call our mutation and to upload the image to cloudnary we created our image crate signature mutation and then we also added this uh image resolver to our schema and then we have those generated files as well so that's what we wanted to accomplish in this video thank you very much see you on the next one
Info
Channel: Leigh Halliday
Views: 5,842
Rating: undefined out of 5
Keywords:
Id: U7RnHHRQ8o0
Channel Id: undefined
Length: 23min 52sec (1432 seconds)
Published: Mon Jul 25 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.