Coding

Angular Image Upload Made Easy

  • 00:00:01 welcome to this video great to have you
  • 00:00:04 here in this video we'll have a look at
  • 00:00:06 how we can upload files from our angular
  • 00:00:09 app to a server as a server I will in
  • 00:00:12 this video use a firebase cloud function
  • 00:00:14 which I wrote in an earlier video on
  • 00:00:17 this channel but any back-end that
  • 00:00:19 accepts form data or binary file uploads
  • 00:00:22 will do so let's dive into this and see
  • 00:00:25 how we can actually get a file from an
  • 00:00:28 input through angular to a server
  • 00:00:34 obviously we need an angular app to
  • 00:00:37 upload files and I'm in a brand-new
  • 00:00:39 project created with the CLI nothing has
  • 00:00:42 been added to this project it's
  • 00:00:43 completely empty I just cleaned up the
  • 00:00:46 app component HTML file and only added a
  • 00:00:49 heading same file upload now I get a
  • 00:00:52 couple of goals here one goal is to add
  • 00:00:54 a file input element that allows us to
  • 00:00:58 well attach files of course I then also
  • 00:01:01 want to upload these files that's one of
  • 00:01:03 the primary goals of this video I also
  • 00:01:05 don't want to show how we can add a
  • 00:01:07 button that indirectly triggers the file
  • 00:01:10 input element in case you don't want to
  • 00:01:12 directly have that in your app but one
  • 00:01:15 step after the other let's start simple
  • 00:01:17 by adding an input of type file this is
  • 00:01:22 a default input element shipping with
  • 00:01:24 HTML which allows us to well get file
  • 00:01:27 inputs one important note if you're
  • 00:01:30 using this in angular form this can't be
  • 00:01:32 registered as a form control where the
  • 00:01:35 attached file would automatically sync
  • 00:01:37 to your form object
  • 00:01:38 you always have to fetch this
  • 00:01:40 differently and you do fetch it by
  • 00:01:42 adding a change listener this will
  • 00:01:45 trigger whenever the file selected by
  • 00:01:47 the user will change which is typically
  • 00:01:49 the point where you are interested in
  • 00:01:51 the fall so here I will execute a on
  • 00:01:54 file selected listener and forward my
  • 00:01:59 event object now I need to add that
  • 00:02:01 listener and DTS foul so on file
  • 00:02:04 selected and I know that I get some
  • 00:02:07 event object here again on file selector
  • 00:02:10 that's just a method getting executed
  • 00:02:12 here now in this on file selected method
  • 00:02:15 I want to do something with that
  • 00:02:17 first of all I'll simply lock the event
  • 00:02:20 to the console so that we can see what's
  • 00:02:22 inside of it
  • 00:02:23 let's save everything and go back and
  • 00:02:25 open the developer console here on the
  • 00:02:27 right and now if we choose a file here I
  • 00:02:30 have prepared one here and I click open
  • 00:02:33 we get this event object where we get
  • 00:02:36 all kinds of information a very
  • 00:02:38 interesting piece of information is in
  • 00:02:40 the target there we get this target
  • 00:02:43 element this is this file input and as a
  • 00:02:45 file input it has this special file
  • 00:02:47 key which is an array of all the files
  • 00:02:50 which were selected in case you have a
  • 00:02:51 multi select tool here I have only one
  • 00:02:55 element so the first element actually is
  • 00:02:57 the file I just chose and this is the
  • 00:02:59 file we can now upload now what you can
  • 00:03:02 do is you can add some logic to
  • 00:03:04 immediately upload the file whenever
  • 00:03:06 this event occurs or maybe you want to
  • 00:03:09 wait until the user presses some button
  • 00:03:11 so maybe you have upload button and this
  • 00:03:16 could of course be also a submit button
  • 00:03:17 and some form of type button where you
  • 00:03:21 then have a click listener or in a forum
  • 00:03:24 DNG submit listener on the overall form
  • 00:03:26 where you then trigger on upload now
  • 00:03:29 this would be an alternative setup we
  • 00:03:31 have this extra on upload function and
  • 00:03:33 in order to use the file here we simply
  • 00:03:36 have to store the file you know may be
  • 00:03:38 selected file property which initially
  • 00:03:41 is null and which we then here set to
  • 00:03:45 this selected file is equal to event
  • 00:03:50 target and then remember we had that
  • 00:03:52 files property where we then had a
  • 00:03:55 couple of Falls let's pick the first one
  • 00:03:56 and that is the file object itself
  • 00:03:59 now we're storing this in selected file
  • 00:04:02 and we can upload it here in on upload
  • 00:04:04 that leaves us with one question how do
  • 00:04:07 we upload a file we do it through the
  • 00:04:10 angular HTTP client for that we need to
  • 00:04:13 go to the app module and enable that
  • 00:04:15 client by importing the HTTP client
  • 00:04:18 module from at angular common HTTP
  • 00:04:24 that's the path to that module we simply
  • 00:04:27 added two imports then and with that we
  • 00:04:29 can inject the HTTP service into any
  • 00:04:32 service or component where we want to
  • 00:04:34 use it now you could create a extra
  • 00:04:37 service for that I'll simply inject it
  • 00:04:39 into my component here so I'll add a
  • 00:04:41 constructor and add my HTTP property
  • 00:04:44 which will be of type HTTP client this
  • 00:04:47 client now needs to be imported so let
  • 00:04:50 me add an import here at the top of this
  • 00:04:51 component HTTP client from and then it's
  • 00:04:54 also add angular common HTTP with that
  • 00:05:00 we
  • 00:05:00 use that client in this component to
  • 00:05:03 upload the file so in on upload I can
  • 00:05:06 then reach out to this injected property
  • 00:05:08 and there I want to send a post request
  • 00:05:12 now the URL I want to send it to
  • 00:05:14 actually is the URL of this firebase
  • 00:05:17 cloud function I created in this this I
  • 00:05:20 guess here this video so this is a video
  • 00:05:23 where I created this function it's a
  • 00:05:25 cloud function which simply accepts
  • 00:05:27 incoming post requests with a foreign
  • 00:05:30 data payload where we can then extract
  • 00:05:32 the file from so I will send a post
  • 00:05:36 request and then I need the URL which I
  • 00:05:40 copy from my firebase console and of
  • 00:05:42 course you can use any other back-end
  • 00:05:44 function that accepts foreign data so
  • 00:05:47 this is the URL I want to send my
  • 00:05:49 request to now I need to configure this
  • 00:05:51 request a little bit I need to add my
  • 00:05:53 body and as I said this body should be
  • 00:05:55 of type foreign data so I will construct
  • 00:05:58 it here I'll name it FD new forum data
  • 00:06:01 which is a default JavaScript object we
  • 00:06:03 can construct and then I will simply
  • 00:06:05 append some fields here for example my
  • 00:06:08 image file which will have a value of
  • 00:06:12 this selected file and where I use this
  • 00:06:15 selected file and now I need to file
  • 00:06:17 name now if you're not sure which
  • 00:06:19 property this is we can get Auto
  • 00:06:21 completion support at least in visuals
  • 00:06:23 to do code by explicitly casting this
  • 00:06:26 year
  • 00:06:27 we know this will be of type file which
  • 00:06:29 is a default JavaScript object and
  • 00:06:32 therefore here we will also store a file
  • 00:06:34 eventually so let's add this type
  • 00:06:36 annotation here too and now we get auto
  • 00:06:38 completion here and we know there will
  • 00:06:40 be a name property so this is now my
  • 00:06:43 whole form data we could also add
  • 00:06:45 additional fields if we needed that I'm
  • 00:06:47 not going to send this or add this as a
  • 00:06:49 body now you don't need to set the
  • 00:06:51 content type that should be set
  • 00:06:52 automatically and we can now instead
  • 00:06:56 simply subscribe to the response so
  • 00:06:59 there we will get a response which for
  • 00:07:01 now I will simply log to the console so
  • 00:07:04 let's try it out I'd say let's simply
  • 00:07:08 first of all pick a file this one here
  • 00:07:11 maybe now it's stored and now let's hit
  • 00:07:13 up
  • 00:07:20 and I get back it worked which is
  • 00:07:23 actually the message my firebase cloud
  • 00:07:24 function sends back if it works I can
  • 00:07:27 confirm this by visiting the storage in
  • 00:07:29 my firebase storage and there I got two
  • 00:07:32 files because of that our image
  • 00:07:33 transformation function I also set up in
  • 00:07:36 an earlier video but there I can confirm
  • 00:07:38 this is the current date and time so
  • 00:07:40 this was uploaded right now so this is
  • 00:07:44 already how easy it is to upload a file
  • 00:07:46 this is all it takes in its basic form
  • 00:07:48 but maybe you want to do more than just
  • 00:07:52 upload the file like this and before we
  • 00:07:55 dive into that just a side note of
  • 00:07:57 course you could have also just sent the
  • 00:07:59 binary itself so just selected file if
  • 00:08:01 your API endpoint accepts that binary so
  • 00:08:05 if it doesn't require form data but
  • 00:08:06 directly wants to binary just a side
  • 00:08:08 note but as I said maybe you want to do
  • 00:08:10 more so let's add an object where we
  • 00:08:14 configure this request now let's say you
  • 00:08:16 want to track the progress of your file
  • 00:08:18 upload then you can add report progress
  • 00:08:20 and set it to true as a config and also
  • 00:08:24 that's important you need to set observe
  • 00:08:27 which normally would be the extract a
  • 00:08:29 response to events this means you will
  • 00:08:32 get all the individual events during the
  • 00:08:34 file upload so now will actually not get
  • 00:08:37 the response here but all events and now
  • 00:08:39 if I save does and I go back to our
  • 00:08:41 application and I choose the same file
  • 00:08:43 again and I upload you see we got
  • 00:08:45 different events here these are the
  • 00:08:48 different upload events and eventually
  • 00:08:50 we get also the response there we got
  • 00:08:53 the different event types and you see
  • 00:08:55 the loaded and the total amount so how
  • 00:08:57 much has been uploaded and how much is
  • 00:08:59 the total amount of to be uploaded we
  • 00:09:02 can use that information by first of all
  • 00:09:04 importing HDP event type here to map
  • 00:09:10 these type numbers to actual names we
  • 00:09:14 can easier understand and then here we
  • 00:09:16 can check if event type is equal to http
  • 00:09:20 event type thing we just imported upload
  • 00:09:24 progress if that's the case then I want
  • 00:09:27 to output upload progress
  • 00:09:32 and set this equal to event and now keep
  • 00:09:37 in mind here we got loaded in total so
  • 00:09:39 if we want to express this as a
  • 00:09:41 percentage its event loaded divided by
  • 00:09:44 event total maybe times 100 and round
  • 00:09:51 that so math.round event loaded by event
  • 00:09:55 total times 100 and then here we could
  • 00:09:59 output percent after this just like that
  • 00:10:03 and if we got a different type so else
  • 00:10:07 if event type is equal to http event
  • 00:10:13 type response well in this case well we
  • 00:10:17 got the response right so we want to
  • 00:10:19 output death so here I can then
  • 00:10:21 console.log
  • 00:10:24 event and that should be my response
  • 00:10:26 let's save that and let's try it out if
  • 00:10:29 I go back and I choose the same file
  • 00:10:32 again and I hit upload you see we got
  • 00:10:35 the upload progress round wasn't the
  • 00:10:38 best idea had always rounded it up to
  • 00:10:41 100% so let me quickly fix this by first
  • 00:10:45 multiplying with 100 here and then let's
  • 00:10:49 try it again so put the multiplication
  • 00:10:53 inside the parentheses and hit upload
  • 00:10:56 again and now you get different upload
  • 00:10:57 progresses and finally at the end after
  • 00:11:00 the responses back we get our HTTP
  • 00:11:03 response here where we could read the
  • 00:11:05 body for example and that is how easy we
  • 00:11:07 can upload a file now let's say we want
  • 00:11:10 to enhance this a little bit and for
  • 00:11:12 some reason we don't want to have that
  • 00:11:14 file input here but I want to have some
  • 00:11:17 other button in our template so let's
  • 00:11:20 say here we have a button which is also
  • 00:11:23 of type button where we have maybe pick
  • 00:11:26 file as a caption and when we click this
  • 00:11:29 then we actually want to trigger this
  • 00:11:32 input which is hidden well that's simply
  • 00:11:35 hired to hide it by setting the style
  • 00:11:37 display to non it will be part of the
  • 00:11:41 Dom but it's not visible well we can
  • 00:11:44 give this a local reference
  • 00:11:46 let me quickly distribute all the
  • 00:11:48 attributes and properties over multiple
  • 00:11:50 lines to make this easier to read we can
  • 00:11:52 get this a get this a local reference
  • 00:11:54 like file input and then here on the
  • 00:11:57 click event on the button we could
  • 00:11:59 simply trigger file input click like
  • 00:12:02 that and that simply proxies to click to
  • 00:12:05 that hidden input so if dead if I save
  • 00:12:08 this I got two buttons if I click pick
  • 00:12:10 file the file picker opens even though
  • 00:12:13 it's hidden and I can still upload the
  • 00:12:15 file just as before but now with the
  • 00:12:17 hidden file picker and that's actually
  • 00:12:20 all I wanted to show you about file
  • 00:12:21 uploads with angular with the HTTP
  • 00:12:24 client you learned how you can track the
  • 00:12:27 progress of the upload how you can
  • 00:12:29 attach a file and fetch a fault to begin
  • 00:12:31 with and that's really all let's do it I
  • 00:12:34 hope this helps you in your future
  • 00:12:35 projects not be
  • 00:12:37 very happy to also welcome you back in
  • 00:12:38 future of videos