WEBVTT

00:00.020 --> 00:04.400
Okay, now that we've got our shiny new image service in place, let's take a look and see how we can

00:04.400 --> 00:07.010
actually upload an image to our API.

00:07.130 --> 00:11.120
And then that image gets sent onto Cloudinary for storage.

00:11.120 --> 00:14.210
And we'll get the URL of that image back from Cloudinary.

00:14.210 --> 00:16.940
So let's take a look at how we're going to deal with this.

00:16.940 --> 00:22.700
First of all, we're going to need to make an update to our product entity as we've got a picture URL,

00:22.730 --> 00:23.480
which is fine.

00:23.480 --> 00:24.950
We'll still use that.

00:24.950 --> 00:32.870
But what we also get from Cloudinary is a public ID of the image that they use as its ID in Cloudinary,

00:32.870 --> 00:38.060
which we need to use if we want to do anything like delete that particular image.

00:38.060 --> 00:41.360
So we'll also store the public ID inside here as well.

00:41.360 --> 00:45.050
So we'll say prop string and public ID.

00:45.380 --> 00:50.810
And we're going to make this optional because of course we don't have all of our original images that

00:50.810 --> 00:57.080
we seeded into our database do not have a public ID, so we need to make that one optional.

00:57.170 --> 01:01.160
Now, even that small change requires us to create a new migration.

01:01.160 --> 01:10.220
So we'll head to the terminal and I'll just stop the API server from running and we'll execute netCDF

01:10.220 --> 01:12.320
migrations ads.

01:13.340 --> 01:19.910
And we'll just say public ID added as the name of the migration and press return.

01:19.910 --> 01:22.850
And this should create this without any issues.

01:22.850 --> 01:29.480
And even though it's such a simple migration, let's just double check what we have inside our new migration.

01:29.480 --> 01:31.430
And we've got our new migration here.

01:31.490 --> 01:34.370
Let's going to do hopefully what we'd expect it to do.

01:34.400 --> 01:38.300
It's going to add a column called public ID to our products table.

01:38.330 --> 01:39.260
Perfect.

01:39.260 --> 01:43.610
So now that we have that in place let's just restart our API.

01:44.420 --> 01:48.050
And then we can go configure the products controller.

01:49.850 --> 01:51.470
And that started fine okay.

01:51.500 --> 01:53.600
So let's go to our products

01:55.580 --> 01:57.530
controller next.

01:58.400 --> 02:03.110
And inside here we're going to take a look at our create product method.

02:03.410 --> 02:08.650
And in fact before we get to our create product method we need to be able to take a file violin as part

02:08.650 --> 02:10.090
of our create product DTO.

02:10.090 --> 02:16.570
So let's go there first to the create product DTO and we're not going to send up a picture URL.

02:16.600 --> 02:19.660
Now we're going to send up something else.

02:19.690 --> 02:28.300
And what we use for this is the AI form file that we used inside our image service.

02:28.300 --> 02:31.180
And we're going to give it a name of file.

02:31.180 --> 02:33.280
And it's not going to be string dot empty.

02:33.280 --> 02:34.480
Because this is an object.

02:34.480 --> 02:39.460
We'll just give it an initial value of null and use the override here.

02:39.460 --> 02:45.610
We're still going to use data annotations for this as well, but we'll just give it an initial value

02:45.610 --> 02:49.660
of null because this is an object and not a string.

02:49.780 --> 02:52.780
Then the default value for an object would be null.

02:52.990 --> 02:59.770
So that's how we'll receive the file from the client, be it postman or the browser.

02:59.770 --> 03:02.050
And let's head back to our products controller.

03:02.050 --> 03:07.480
And then we can check our create product DTO and see if it has a file inside it.

03:07.480 --> 03:09.850
So not something we can use Automapper for.

03:09.880 --> 03:12.230
Of course we need to actually do something with this.

03:12.230 --> 03:15.680
And inside here we're also going to need access to our image service.

03:15.680 --> 03:17.810
So let's add this at the top as well.

03:17.810 --> 03:24.830
So I'm going to add in the image service and call it image Service and just move this down as well.

03:25.040 --> 03:30.860
So back to our create product method below the mapping code.

03:31.010 --> 03:37.580
We'll check to see if the product DTO dot file is not equal to null.

03:38.450 --> 03:42.800
And if that is the case, then we'll create a variable to store the image result in.

03:42.800 --> 03:46.610
And we'll set it equal to await image service.

03:46.610 --> 03:49.730
And we'll use our add image async method.

03:49.730 --> 03:53.510
And we'll pass in the product DTO dot file.

03:54.680 --> 03:56.720
Then we can check the image results.

03:56.720 --> 04:03.860
And we'll check the image result dot error and see if that is not equal to null.

04:04.280 --> 04:14.150
And if it is not null, then we're going to return a bad request and we're going to pass in the image.

04:14.150 --> 04:15.470
Result Dot error.

04:15.500 --> 04:16.820
Dot message.

04:16.850 --> 04:22.580
The error messages that we get back from Cloudinary are good enough to work with, and they'll tell

04:22.610 --> 04:26.060
us exactly what the problem is if we've got a time period in our cloud name.

04:26.090 --> 04:31.130
It'll tell us there's a problem with the cloud name, and same goes if we've got any problems with our

04:31.130 --> 04:36.200
configuration settings that we're using for this, then do keep an eye on what that error message is

04:36.200 --> 04:37.190
telling you.

04:37.730 --> 04:40.130
To see what the problem is.

04:40.820 --> 04:45.500
And then we can set our product with the result of what we get back from Cloudinary.

04:45.500 --> 04:52.820
So we'll set the product dot picture URL equal to be the image results dot secure URL.

04:52.820 --> 04:59.990
And then we can use the absolute URI, which is going to give us the URL that Cloudinary uses so that

04:59.990 --> 05:02.690
our client browser can download that image.

05:02.690 --> 05:09.110
And then we'll also set the product's dot public ID inside here and set that to the image results dot

05:09.110 --> 05:10.760
public ID.

05:12.260 --> 05:14.330
And then the rest of the code stays the same.

05:14.330 --> 05:18.790
We can just go ahead and add our product and then save it into the Database.

05:19.150 --> 05:22.150
So we should be able to now test this functionality.

05:22.180 --> 05:24.670
So let's head across to postman and do just that.

05:24.700 --> 05:30.220
Inside here I do have a method here to create a product with a file.

05:30.220 --> 05:36.670
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

05:37.420 --> 05:41.170
of the request, just as we have been doing, but we can't send this up as JSON.

05:41.170 --> 05:43.480
We have to send this up as form data.

05:43.480 --> 05:45.910
So that's what we're using here.

05:45.910 --> 05:48.700
And then otherwise it's pretty much the same thing.

05:48.700 --> 05:52.450
We set the different properties the name description, the price and the file.

05:52.450 --> 05:54.670
This is the one that we need to set.

05:55.030 --> 06:03.880
And inside here just clear whatever is inside there and select new file from local machine.

06:04.240 --> 06:13.180
And I'm just going to use one of the images I already have inside the Restore Client public images folder

06:13.180 --> 06:14.620
where we've got our products.

06:14.620 --> 06:17.500
And I'm just going to pick one of these images.

06:17.500 --> 06:19.960
Doesn't matter which one, I'm just going to go for the first one.

06:19.960 --> 06:22.030
We're just testing image upload.

06:22.060 --> 06:28.240
If you want a proper image that's different to the other products, then please go to a place like Unsplash

06:28.240 --> 06:34.180
where there's a ton of images you can download free of charge, and you can search for ski related images

06:34.180 --> 06:35.230
if you wish to do so.

06:35.230 --> 06:41.500
But I'm really just testing the upload functionality here and this will tell us if that is going to

06:41.530 --> 06:41.860
work.

06:41.860 --> 06:44.500
So I'm going to use this one just as an example.

06:44.500 --> 06:50.590
I still get a little warning here, and it tells me that the above is not in your working directory

06:50.590 --> 06:54.370
and will be unavailable to teammates when you share the request.

06:54.370 --> 07:00.070
This is just telling us that this image is not available to other users of postman.

07:00.070 --> 07:05.770
If we're sharing our collection and working in a collaborative environment, that doesn't mean it's

07:05.770 --> 07:07.480
not available from our local machine.

07:07.480 --> 07:07.900
It is.

07:07.930 --> 07:09.370
We've just selected it from there.

07:09.370 --> 07:12.940
So that warning doesn't tell us anything useful for what we're doing.

07:13.000 --> 07:17.860
And then we've got the type, brands, quantity and stock, etc. so if I click send, what we should

07:17.860 --> 07:25.860
expect to happen here is that Hot Reload has let us down once again, multiple constructors, blah blah

07:25.860 --> 07:26.100
blah.

07:26.130 --> 07:28.530
This is not a real problem.

07:28.530 --> 07:34.050
And I'll just go back to the terminal and I'm just going to restart the API.

07:34.050 --> 07:38.460
And then I'm going to head back to postman and repeat that request.

07:38.460 --> 07:40.170
So I'll click send again.

07:40.170 --> 07:43.080
And this time we see the loading taking place.

07:43.080 --> 07:45.990
And what should happen is we get the 201 created.

07:45.990 --> 07:53.760
And what should have also happened is we've got the public ID and the picture URL populated from what

07:53.760 --> 07:59.100
we get back from Cloudinary as well, so we can see the public ID that's a combination of the folder

07:59.100 --> 08:05.520
that this has been uploaded into, along with its ID that's what we'd need to use to delete this particular

08:05.520 --> 08:07.110
image from Cloudinary.

08:07.110 --> 08:11.610
And we've got a URL provided from Cloudinary where that image is stored.

08:11.610 --> 08:14.700
And we can click on this and we can send.

08:14.820 --> 08:19.710
And what we should get is the image coming back from Cloudinary, which we can see there.

08:19.710 --> 08:20.940
Perfect.

08:21.330 --> 08:24.210
So that proves the image upload is working.

08:24.210 --> 08:29.700
And next we'll take a look at the edit and delete options for our images as well.
