Okay, now that we've got our shiny new image service in place, let's take a look and see how we can
actually upload an image to our API.
And then that image gets sent onto Cloudinary for storage.
And we'll get the URL of that image back from Cloudinary.
So let's take a look at how we're going to deal with this.
First of all, we're going to need to make an update to our product entity as we've got a picture URL,
which is fine.
We'll still use that.
But what we also get from Cloudinary is a public ID of the image that they use as its ID in Cloudinary,
which we need to use if we want to do anything like delete that particular image.
So we'll also store the public ID inside here as well.
So we'll say prop string and public ID.
And we're going to make this optional because of course we don't have all of our original images that
we seeded into our database do not have a public ID, so we need to make that one optional.
Now, even that small change requires us to create a new migration.
So we'll head to the terminal and I'll just stop the API server from running and we'll execute netCDF
migrations ads.
And we'll just say public ID added as the name of the migration and press return.
And this should create this without any issues.
And even though it's such a simple migration, let's just double check what we have inside our new migration.
And we've got our new migration here.
Let's going to do hopefully what we'd expect it to do.
It's going to add a column called public ID to our products table.
Perfect.
So now that we have that in place let's just restart our API.
And then we can go configure the products controller.
And that started fine okay.
So let's go to our products
controller next.
And inside here we're going to take a look at our create product method.
And in fact before we get to our create product method we need to be able to take a file violin as part
of our create product DTO.
So let's go there first to the create product DTO and we're not going to send up a picture URL.
Now we're going to send up something else.
And what we use for this is the AI form file that we used inside our image service.
And we're going to give it a name of file.
And it's not going to be string dot empty.
Because this is an object.
We'll just give it an initial value of null and use the override here.
We're still going to use data annotations for this as well, but we'll just give it an initial value
of null because this is an object and not a string.
Then the default value for an object would be null.
So that's how we'll receive the file from the client, be it postman or the browser.
And let's head back to our products controller.
And then we can check our create product DTO and see if it has a file inside it.
So not something we can use Automapper for.
Of course we need to actually do something with this.
And inside here we're also going to need access to our image service.
So let's add this at the top as well.
So I'm going to add in the image service and call it image Service and just move this down as well.
So back to our create product method below the mapping code.
We'll check to see if the product DTO dot file is not equal to null.
And if that is the case, then we'll create a variable to store the image result in.
And we'll set it equal to await image service.
And we'll use our add image async method.
And we'll pass in the product DTO dot file.
Then we can check the image results.
And we'll check the image result dot error and see if that is not equal to null.
And if it is not null, then we're going to return a bad request and we're going to pass in the image.
Result Dot error.
Dot message.
The error messages that we get back from Cloudinary are good enough to work with, and they'll tell
us exactly what the problem is if we've got a time period in our cloud name.
It'll tell us there's a problem with the cloud name, and same goes if we've got any problems with our
configuration settings that we're using for this, then do keep an eye on what that error message is
telling you.
To see what the problem is.
And then we can set our product with the result of what we get back from Cloudinary.
So we'll set the product dot picture URL equal to be the image results dot secure URL.
And then we can use the absolute URI, which is going to give us the URL that Cloudinary uses so that
our client browser can download that image.
And then we'll also set the product's dot public ID inside here and set that to the image results dot
public ID.
And then the rest of the code stays the same.
We can just go ahead and add our product and then save it into the Database.
So we should be able to now test this functionality.
So let's head across to postman and do just that.
Inside here I do have a method here to create a product with a file.
And the way that we send this up in postman so that we can send up a file is we need to use the body
of the request, just as we have been doing, but we can't send this up as JSON.
We have to send this up as form data.
So that's what we're using here.
And then otherwise it's pretty much the same thing.
We set the different properties the name description, the price and the file.
This is the one that we need to set.
And inside here just clear whatever is inside there and select new file from local machine.
And I'm just going to use one of the images I already have inside the Restore Client public images folder
where we've got our products.
And I'm just going to pick one of these images.
Doesn't matter which one, I'm just going to go for the first one.
We're just testing image upload.
If you want a proper image that's different to the other products, then please go to a place like Unsplash
where there's a ton of images you can download free of charge, and you can search for ski related images
if you wish to do so.
But I'm really just testing the upload functionality here and this will tell us if that is going to
work.
So I'm going to use this one just as an example.
I still get a little warning here, and it tells me that the above is not in your working directory
and will be unavailable to teammates when you share the request.
This is just telling us that this image is not available to other users of postman.
If we're sharing our collection and working in a collaborative environment, that doesn't mean it's
not available from our local machine.
It is.
We've just selected it from there.
So that warning doesn't tell us anything useful for what we're doing.
And then we've got the type, brands, quantity and stock, etc. so if I click send, what we should
expect to happen here is that Hot Reload has let us down once again, multiple constructors, blah blah
blah.
This is not a real problem.
And I'll just go back to the terminal and I'm just going to restart the API.
And then I'm going to head back to postman and repeat that request.
So I'll click send again.
And this time we see the loading taking place.
And what should happen is we get the 201 created.
And what should have also happened is we've got the public ID and the picture URL populated from what
we get back from Cloudinary as well, so we can see the public ID that's a combination of the folder
that this has been uploaded into, along with its ID that's what we'd need to use to delete this particular
image from Cloudinary.
And we've got a URL provided from Cloudinary where that image is stored.
And we can click on this and we can send.
And what we should get is the image coming back from Cloudinary, which we can see there.
Perfect.
So that proves the image upload is working.
And next we'll take a look at the edit and delete options for our images as well.