Node.js File Upload API with Express Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
uploading files to a node.js rest api can be very useful and the express file upload package has nearly 1 million downloads per month however when i check the documentation for multi-file upload support it suggests that i create one html input on my page for each file that i wish to upload at the same time well i've made a few changes and for the node.js file uploader that we create today you'll be able to use only one input to select multiple files and after we select those i'll click submit and we have a success message and you can see the files have now been uploaded to our nodejs server [Music] hello and welcome i'm dave we'll be learning how to upload files to a node.js rest api server i'll provide links to example source code and all resources in the description below this is not a beginner node.js tutorial so just a reminder before we get started that this is more of an intermediate to advanced level tutorial you'll surely understand more of what i do in this tutorial if you've completed my nodejs course for beginners first okay i've got vs code open and we're starting with an empty project folder i've already got the terminal window open as well and i'm going to assume you have both node and npm already installed as i'm also assuming you are not a beginner so now i'm going to type npm init to start our project and then press dash y so it won't ask us all of those questions in the beginning and then after that we need to install a couple of dependencies so npm i and then express and then a space and then express dash file upload i almost type download and we'll get both of those dependencies installed and that was quick now we want one dev dependency also so i'm going to type npm i and then nodemon as nodemon will restart our app anytime we save changes to it and so then dash capital d so it's installed as a dev dependency and now it's already installed too so let's close the terminal window and look at our package json under dev dependencies we see nodemon and then under dependencies we see express and express dash file upload now up here we have the name of our project which is node file uploader and then it has tut after it so that is just because that's what i named the folder that's short for tutorial i'm going to change the main value here from index.js to app.js so inside of the scripts curly braces let's put start and a colon and then we'll have node space app.js and a comma but after that we'll also put a value for dev and here we'll use nodemon app.js and put a comma there as well and now we're finished with our package.json let's go over to the file tree now and create a new file and we'll name this app.js i'm just going to paste in some code and we'll go over it but this is basic code that you should have when you start basically any server except for the file upload that we're using specifically today so we are importing in express here with requireexpress then we're importing in the express dash file upload middleware and naming it file upload then we're also importing the path module from node and that's just require path after that we're defining our port so we use process.env.port or 3500 so we'll be running this on localhost 3500 today then we're setting our app equal to express and then what's usually at the bottom of our file is on line 9 here and i can give it some space but it's app.listen then we provide the port value and then the callback function right here is just logging server running on port and listing that port so we could start our server right now it wouldn't do anything but it would say it is running on port 3500. now just underneath the app that we defined so i'll put this on line 9 we're going to define a route for our index.html basically the default web route here at the slash or the root of our application and it gets the request and the response we don't need to send a next into it and then we're just going to send the file and we're using the path module here to call path.join choosing the directory name and that's a value that is found in node and i do go over that in my course for beginners and then you've got the index.html which is the default page so that's what we're going to need to create next so back to the file tree let's create a new file and we'll name this index.html now i can type an exclamation mark for the emit abbreviation and get a basic outline of a page already now we can just put our title in here which would be node js file uploader and after that inside of the head i'm going to paste some css that i've already made and we're not going to use separate files i'm just going to stick all of this inside of the html file there's not a lot of css though after that we can create the body of our page i'll put an h1 and inside the h1 we'll just put the title once again node.js file uploader i should mention that of course these resources will be available in the description so if you specifically want to use the css i put in here which is not much you can either pause the screen hour or of course access that repository and get the css from there but i'm not going to go over each line of the css okay after that we have a form and the form does have an action attribute instantly but we don't need the action attribute today we're just going to use an id equal to upload form and then we need to set the encryption type it says here or enc type i think that's encryption i'd have to look that up to confirm that suspicion actually but we want multi-part dash form data and then inside the form we're going to put our input we need in there not m input the type is going to equal file and after that we'll give this an id and set it equal to my files and then after that we want to use this for images today so i'm going to say accept equals and then we'll put image slash and an asterisk and this as far as on windows which i'm on is when you open up the window to browse for files it's only going to show you this type of file first you can manually change that once you have that window pop up but it's going to only display the image files which should help somebody out that wants to upload images and then we put in the multiple attribute here and it doesn't have an equals value we just say multiple and then we can close out the input after that let's just put a button and let's say the button says submit we can save that much but i want to put an h2 and an h3 afterwards that we can write some data to so we'll just leave those empty for now an h2 and an h3 there after that now this is just going to be vanilla javascript but i'll just put a script tag and we'll put our vanilla javascript right inside this script tag and i should add that i just want to do this in vanilla javascript to have this all in one repository so it's just all in the index.html file because our focus is on the node.js code today however in the future if you want me to make a react front-end form to upload images with the back-end that we're creating today i could do that as well so let me know in the comments here let's just define our form and set this equal to document.getelementbyid and here we can choose our upload form after we do that let's define a function called send files now this will be an async function because we're going to use fetch here in vanilla javascript and now inside this function i'm going to scroll so we have some more room inside the function we're going to get an object and this object will define it as my files we'll set this equal to document.getelementbyid once again and this will be the id my files so that's the input itself and then afterwards we say dot files and now we'll have an object that has all of the files that the user has selected now we need to define our form data so we'll say form data equals new form data and after we've created the form data we need to bind or append the file data that we selected to the form before we send it because the express file upload package expects to get that informed data so what we'll use here is object dot keys we'll pass in my files which remember is the files we're getting from the input and it is an object so we'll say four each then we'll have a key so for each key we'll take the form data and we'll call append then we'll have my files and then we'll say dot item and we'll take the key and then get the name so this will end up being the key for the file as we send it to our node.js backend and then we'll actually send the file itself which we refer to as my files dot item with just the key and not the name property attached right there so this is actually going to be the key for the file object and this is the object itself right here so now that we have looped through that we're ready to send this to the node.js backend so we'll create a response set this equal to await fetch now this will be the back end here for our dev environment so it's just http colon slash slash local host port 3500 and we're going to create an upload endpoint but after that we need to put in the config object for fetch so this method will be post and after that we'll have the body and that will be the form data we created i'm going to scroll for some more room again but we know after fetch we're not using axios here so now we actually need to get the json from that response so let's just say const equals and we await response dot json now from here we could just log this to the console so i'll do that but let's go ahead and put this on the page where we have this empty h2 and h3 also so i'll scroll back down and i'm just going to paste this in quickly so what we've got is the h2 we're selecting that with our query selector then we're setting the text content of the h2 to status and it's showing the status property from the json that we have and likewise we're doing this for the message with the h3 so now we've created our send files function but we still need to call it so i'll scroll just a little more and underneath that we need to listen for the form submission so we'll say form dot add event listener we're listening for the submit event and there's the event and now inside of this the first thing we'll do is event dot prevent default so it doesn't reload the page and then we'll call our send files function and save and now we're finished with this file and as i complete this vanilla javascript which i've been working with react for a while some of the things that we take for granted and react make it so much easier at times than vanilla javascript but this shows how to do this and of course i could make this into a react front-end project in the future we're now ready to go back to our app.js so now inside of app.js we need to create our upload route so this will be app dot post and now we'll look for slash upload and after that we'll put a comma and this is where we could put middleware and we do have some middleware and that is the file upload middleware of course you could put app.use up here and use it on all routes but we don't really want to use the file upload middleware on all routes so let's just use it on our upload route which makes sense and we can pass options in here unfortunately many of the options that come with express file upload are just for those single files or one at a time as it showed using more than one input and so i've found that some of the things like the file size limit and things like that only apply to the first file when you do it with one input so we're going to create our own middleware to handle some of that today too but here we'll put create parent path and set this to true after that we could put a comma and add some more middleware if we want to but after we get through all of that let's get the post down here so i'm on the right line for everything because this is where it actually ends the post after all of that i need to put a comma even any other middleware we would add and now we call our function here so we have a request and response and at this point let's just get the files so we'll define files and we can set that equal to request dot files because that's where they'll come from when we're using this file upload middleware let's just say console.log and we'll log the files now we could give a response as well so let's just return a simple response here we'll say res.json and we're expecting a status and a message so status right now we'll just say logged and then for a message we'll also say logged and we can save this and before we add any more we're ready to go ahead and at least try out the server and see if our front end is working or if we have any errors there right now before we add the extra middleware and before we actually write the files to the server so remember this console log will actually show in the node.js console and not in the browser console so control and back tick now let's type npm run dev to start our application with nodemon and now it's running we can close this again if we want to or we can open it back up so we see that console log statement so let's drag this over and i'll hold down shift so it locks to that window and we've got our front end page right here so i'm going to choose a file and i've got a couple of image files here i can choose one or even two or however many i want to and we'll see if they log when we submit the files and they sure did so look we're looking at the actual objects here that node receives and it's already been processed of course by that express file upload middleware so here is the key which is the name of the file as well and then it has a name property it has some data there also we have the size encoding temp file path a truncated value an md5 value and a move function which we will use so the express file upload middleware does a couple of things we really like it gives us that move function it handles creating the file folder when we need it to and that's the option we put in although we're not writing it yet so it's not doing it and it's overall just handling these files and putting them in the request.files property as well just like we need it to so it's still worth using we're just going to change some of those options because it doesn't support support those when we use only one input okay let's drag vs code back over to full screen we're going to need all of that and let's create a new directory over here and we'll call this middleware now inside the middleware folder let's create a file and we'll call this files payload exists dot js and what we're doing is taking some logic that you may see in an example all in one big function but we're extracting some of this from say a big function like we would have here in the upload route because we could use this on more than one route in the future say we had a separate route that was going to upload pdf files or excel files for work or whatever is needed we would want to just write this once instead of write it for every single route so with this middleware now we'll say const files payload exists and set this equal to what you would expect request response and next and then inside the function we're just going to say if there are no files essentially which is request dot files and we're using that exclamation mark to say the opposite of that then we're going to return we'll say res status 400 which is a bad request and then we can put our value here inside the json i'm going to press ctrl b real quick to hide the file tree for just a little more room and then inside the json we'll have a status and here we'll set that to an error and then we'll have a message and here we'll say missing files so that's all this middleware is really going to do it's going to see if we have supplied the files or not and if we don't receive any files it's going to send the error otherwise we'll call next and move on to the next middleware after that we need to remember to go ahead and do module.exports and set this equal to our files payload exist at the bottom and we're finished with our first middleware okay let's go back to the file tree and create a second middleware this is going to be called file not files just file size limiter dot js at the top of file size limiter we're going to define a couple of constants i'm going to create this one called mb and set it equal to five which is going to represent i need a semicolon there actually this is going to represent five megabytes and that's going to be our file size limit but let's now define file underscore size underscore limit i'm using all caps on these because i'm going to refer to them as actual constants but here this will use that megabyte value and then we take it times 1024 times 1024 and that will create that five megabyte number and we don't want files to be any larger than that okay now we can start the function itself so we'll say const file size limiter equals function with request response and next as a good middleware function should and then we'll define the files with const files and we'll set that equal to the request dot files after we get that let's define a empty array so files over limit and this will hold the names of any files that go over the limit we have set so now we need to determine which files are over the limit and we'll once again use object dot keys we'll pass in the files we'll say for each key and now inside the function we can say if files and will refer to the key and then we can get the size property that we have so if that is greater than our file underscore size limit then we want to issue the response or at least we're not issuing the response yet we're actually just storing the name of the file that is over the limit so we can report all files that are over the limit so this is files over limit dot push and then we'll need to pass in the files and the key and then we'll say dot name so we get an array that has all the names of the files that are over the limit and now we can send our response if files over limit has length so if the array has any items in it this is where we'll send the response and underneath that we would call next and just so i don't forget underneath all of this we still need to have our module dot exports and set this equal to file size limiter okay so inside of this if now i'm going to paste in some things that i am just probably too picky about but i'm trying to have good grammar inside of my error message essentially so i'm creating an error message here and this is sometimes the perfectionism that i fight in my own life i guess but what i wanted to do was know whether i should use the word are or is inside of this sentence and so i'm saying the upload failed and then we're passing in the array and setting it to a string so it could have one or more file names here and if it has more than one we're going to use r if it only has one we use the verb is after that we also have the value the constant from above saying how many megabytes and then i'm using replace all because if there is a list of files they won't have any spaces between they'll just have a comma so i'm replacing the comma with a comma space after all of that then i realized that okay maybe there's a comma and we need the word and and then of course if there's a list of three or more i need to keep some of the commas so this just grabs the last comma with this regex and puts in the word and so that's probably me just being too picky but after all of that we just need to return our response and that response goes right here at the bottom so i'll add one extra line and let me save to get better formatting but there we go we're returning a status 413 that says the file or a file is too big and then we have the status is an error and we just need to pass in the message since we've got a message variable and a message property we don't need to say message message we just put in message once and it will pass that in back to the file tree we have one more middleware to create and this is going to be file ext limiter so it's file extension limiter dot js now this one is just a little different because it will receive a parameter and we did this with a verify roles middleware in my node.js course as well so this is constructed just a little differently because of that parameter so first let's bring in the path module we'll say require and get path after that we'll start defining our function it's file ext limiter and this is going to equal a function that receives an allowed ext array so an allowed extension array and now inside this function which will be called immediately when the node.js app loads it will return a function to be called in the path which is middleware so that's request response and next and then inside of this function we can refer to that allowed external array that is passed in and that is closure that is this file extension limiter will have executed and already closed but the function that it returns will still have access to this allowed extension array that is passed in above it's in the lexical scope of this function okay so inside of here we need to once again get the files first so we'll say const files is going to equal the request dot files after we do that let's define another empty array and we'll call this one file extensions and set this equal to an empty array now we'll use object dot keys again pass in files four each and this is for each key here we'll say file extensions dot push i'll back this up to spell push correctly now we'll say path dot ext name so we get the extensions from each file and then we'll have files and of course key and then dot name so we're grabbing the extension from each of the files inside that file object so now we'll have an array of the file extensions after this we need to determine if the file extensions are allowed so let's say are the file extensions allowed let's define a variable called allowed and here we'll compare the arrays that we have the file extensions array versus the allowed extension array so we'll use file extensions dot every so we want every one of these to be true as a result we'll pass the extension and now we'll say allowed ext array there we go dot includes and this would be the extension itself okay after that we'll know we'll either have a true or false either they're all going to be true or it will be false with the every here that we're calling on the array so after that we can just say if it is not allowed then we're going to send a response and otherwise of course we're going to call next once again while i'm here i need to add that module exports at the bottom so module dot exports and i'm in the wrong place it needs to be after that curly brace so here we go module dot exports equals file ext limiter there we go we can get rid of the space between those two and now we just need to handle our response here and this response is going to go right here inside the if not allowed and here i can press alt z to get this code to wrap so we can see it a little better so our message now is once again upload failed we're passing in the allowed extension array to string so it tells the user what extensions were allowed only those are allowed and i'm doing a replace here with the commas again as well and this is a 422 so it will be a little different and we'll test out that error message as well let's save this file and jump back to the app.js okay if i scroll up to the top and now just underneath where we imported the path i'm going to paste this in so we see all three but what we've got here is an import of our files payload exists and we're requiring going to the middleware folder and getting that middleware and we're doing that for each one of these middleware that we created and now we can put them below inside of the route here for our app.post our upload route so after the file upload and before this function that we have at the very end of the route we want to put these other middlewares so we have files payload exists and a comma now the next one is the file extension limiter and here this needs to receive that array that has the files extensions we will accept so we want dot png and then we'll also accept jpg then we'll also accept jpeg sometimes jpeg files have that extension so we'll accept any of those now notice this has parentheses here it's a function that is being called immediately but remember it returns a function and then that function that it returns is the middleware that will sit in the route okay the final one is the file size limiter and we put a comma after it because it does not receive any parameters so now we've got all of our middleware added to the upload route let's save our app file i'll quickly press ctrl in the backtick to make sure that we're still running and yes we're still running here on port 3500 and you can see nodemon restarts after each change so i'll go ahead and close this out let's drag this over to the left again and i'll reload this so now let's check out our error messages the first one would be for the files payload exists so if we don't submit any files we get an error and we're missing files so that works now the extension limiter so now let's choose files again notice let me drag this over where you can see all of it notice that this might be really small but it's only suggesting image files right now but i can change this and choose all files and i have a mislabeled png here that is dot pnk so i'm going to select that and submit and now it says upload failed only png jpg and jpeg files are allowed so that middleware is also working now let's try the file size limiter so i'll open this back up i chose galaxy here you can get any of these images from unsplash is where i got some of these space images the ones with stars always seem to be larger than others at least i've noticed so if i submit galaxy it says upload failed galaxy jpeg is over the file size limit of five makes now let's do this with more than one let's select all three of these and see if that message effort we put in pays off so now we have upload fails galaxy jpeg comma space star force jpeg and stars jpeg are over the following so that extra code in there for the grammar is working out okay so everything's working with our middleware so the next thing we need to do is just write the files to our server i'm going to drag visual studio code back over to the full screen and now we're ready to write the files right here underneath where we're logging the files to the node console i think i'll scroll for just a little more room because we'll need it so i'll once again use object dot keys and we'll pass in the files and now we'll say for each key and inside we'll have our function the first thing we'll do here is define the file path so const file path is going to equal path dot join and then we get that directory name variable from node we're going to have the files directory where we store our different image files we could name it images if we want to but we're going with files for the example then we'll get the files dot key or not dot key bracket key dot name there we go so that will be the full path so this will have the directory path the folder and the file name now that we've defined our file path we can call the files whichever file it is files and then key in brackets and now remember our middleware express dash file upload has attached a function we can call and it is the mv function and we just pass in the file path and then if there's an error we could handle that here and at this point we won't do much we'll just say if error return and now let's go ahead and give a status of 500 which would be a server error and we'll go ahead and attach some json onto that so we can say status error and then we'll go ahead and add the message that is expected and we'll say oh we don't need quotes we'll just pass in the error now i'm going to press alt z to wrap that code it's getting just a little long and now we already have a return statement here but let's say something different than logged so if it reaches this point it's going to be a success and our message will change so what we can do here is once again do object dot keys and pass in the files and then say to string so it just takes that and makes a string of all the file names so we have a success and we get a string of all the file names that we have successfully loaded and save but we'll also want to watch over here because it should create a file directory if we successfully upload those files let's once again open the terminal and let everything is running now on port 3500 so nodemon has kept it going i'm going to drag visual studio code over to the left we'll keep our eye on the file tree as well i'll reload this page and now let's just choose some files so i'll choose the two that i know will upload that are not over the file limit and i'm not sure you could see those on the screen maybe i'll drag this over and do it again here's the two i'm selecting and i'll click open and now i'm going to click submit and yes we now have a files directory here we've got both of the files uploaded to the server success everything is working as it should so i hope this has helped you understand how you can add a path to your rest api possibly the rest api created in my node.js course but either way whatever node.js rest api you have you can now add an upload path and you can upload the types of files that you want to we used images as an example but it doesn't have to be images these could be pdfs it could be excel files text files whatever types of file you want to look for and we've extracted a lot of the logic into our own middleware so we could reuse this on different paths that we create inside of our api as well remember to keep striving for progress over perfection and a little progress every day will go a very long way please give this video a like if it's helped you and thank you for watching and subscribing you're helping my channel grow have a great day and let's write more code together very soon
Info
Channel: Dave Gray
Views: 56,686
Rating: undefined out of 5
Keywords: node.js file upload, node.js, node, nodejs, node js file upload api, node.js rest api, node.js api, node api, node.js endpoint, node endpoint, express file upload, node express, express-fileupload, node.js express tutorial, node tutorial, node.js tutorial, express tutorial, node image upload, node.js image upload, node file upload, how to upload files with node, upload files with node.js, node upload files, node.js upload files, node js upload file to server, javascript, files, js
Id: 4pmkQjsKJ-U
Channel Id: undefined
Length: 35min 25sec (2125 seconds)
Published: Fri Jun 17 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.