Node.js Image Uploading With Multer

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey what's up guys so uploading files in images is an important part of app development and I realized that I don't really have any tutorials showing you guys how to properly upload images in nodejs so in this guide we're going to explore the multi module which is pretty powerful and I'd say probably the most popular way to upload files locally and I wanted to create this tutorial because the documentation for multi although it has a lot of information as far as the API goes it doesn't really give you any full examples so that's what we're gonna do we're going to just create this little application here where we can upload a file we're using a materialized CSS UI and we're gonna use ejs which is embedded javascript for our template engine and we can just click click this to upload a file so we'll grab this image here and submit it and it's just going to show down here and if we go to the directory that this is in which is right here you'll see in public we have uploads and it got uploaded now if you upload the same file it'll just get renamed you can see it has just a timestamp on the end of it not the most elegant solution to rename but if we have enough time I will show you a better way to do it alright and of course we did implement some safeguards like if we just refresh this if we try to submit without choosing a file it'll tell us to choose a file if we choose like a JSON file something that's not an image it's not gonna let us it'll give us an error we have size limits so I'm gonna show you quite a few things with with Malter alright so that's it let's go ahead and get started coding dojo is a programming school that turns beginners into developers in only 14 weeks over 90% of their grads land jobs within three months of graduating often making over seventy K per year to learn more visit coding dojo com or click the link in the description below alright guys so don't let the fact that mon linux throw you off i actually created this on windows I just felt like using Linux so this is completely cross-platform I just have vs code open I have a like folder called node uploads and I'm using my integrated terminal down here alright so first thing we're gonna do is create a package JSON file with NPM and knit so we're just gonna go through this description will say example for image uploading and node entry points gonna be apt J s and we'll just enter through the rest alright so now we have our package JSON file so we're gonna need a couple dependencies here so let's do NPM install - - save we want to Express we want ejs which is the template engine we're using really easy to set up and then we want multiply uploads okay those are the three dependencies that we want alright i'm also going to create a start script i'm just going to replace test with start and we'll set that to node app dot j s that way you can run your application with npm start now I like to use node Mon so I don't have to keep refreshing my server every time I make a change so to clear that out let's install node Mon globally I'm on Linux so I have to say sudo npm install - ji node lon obviously if you're on Windows you don't need to use sudo so that'll just constantly watch our application so we don't have to keep reloading it alright so now let's create the main app j/s file so we'll say new file app dot j s and we're just gonna basically bring everything in now I'm not gonna be explaining like the basics of Express you guys should probably learn that first before you start dealing with file uploads if you don't know that already so we're gonna bring in Express require press we're also gonna bring in multi alright let's bring in ejs which is embedded JavaScript that's our template engine and we're also going to bring in the path module which is a core node.js module so that's why we didn't have to install it alright so now we want to just init our app variable so let's say Const app equals Express and then we're gonna create a variable for our port number which will be 3,000 and then we're just gonna do app dot listen this is just standard Express stuff passing the port then we'll have an arrow function and we're just gonna console dot log we'll put a template string in here so I'm going to use backticks and we'll say server started on port and since we use backticks and a template string we can put in a money sign curly braces and then put in a variable and we're gonna put in that port variable alright so that should be enough to actually be able to run this now since we installed node Mon we should be able to just say node 1 and you can see started on port 3000 go to localhost 3000 then we're gonna get cannot get slash so cannot get slash just means that we don't have a route for for the index page so the index route so let's create that say app dot get slash and all we're gonna do here is render a template so I'm gonna say res dot render and we'll render a template called index or a view I should say now this isn't going to work yet because we haven't set up ejs or our views ejs is really easy to set up we just basically need to put in one line here we just need to set the view engine so we'll say app dot set and we'll save you space engine and then set that to ejs all right I also want to set a static folder okay we're gonna set it to our point we're going to set it to public to a folder called public so we can do that with app dot use Express dot static and we want that to be dot slash public all right so it's just gonna look at we're gonna create a folder called public and that's gonna be static so we can for instance we can go to you know our application localhost 3000 slash and then if we had like a CSS folder in there we could go to slash CSS Styles whatever where that's where we're gonna put our images okay we're gonna create a file a folder called uploads inside of the public folder so let's go ahead and save this and we're gonna create a couple folders over here let's create public and inside public will create uploads alright we'll just leave that for now that's where our images will go we also want to create a views folder and inside views we're gonna create a file called index dot ajs and in here we'll just say index view save and then let's reload res is not defined so for the app get route I forgot to put in request response okay whenever you create a route you need to add in your request response parameters all right so we'll reload and now we get index view so we're now loading the view so before we go any further in app guess let's create our view which is going to be HTML obviously so I'm just going to put in some basic HTML tags using Emmet and in here and the title will say node file uploads I'm gonna go kind of fast guys because I don't want this to take forever and there is quite a bit of stuff that we need to cover all right so we're gonna use materialized so let's go to materialized CSS what is it yeah materialized CSS comm hit get started and we're gonna just grab the CDN which is right here so this is this for the CSS we'll copy that put it in the head tag and then the JavaScript which is just right here we're gonna copy and we're gonna put that right above the ending body tag now materialized the JavaScript for materialized needs jQuery so let's go ahead and search for jQuery CDN this first link here and we're going to get the minified version of jQuery 3 so we'll just need to copy this script tag here and then we can close that up let's paste that right above the materialized script make sure it's above it and then that should be good as far as you know including scripts so inside the body let's let's put a class of container which will move everything into the middle then we're going to put an h1 we'll say file upload cannot spell file upload alright and then I'm gonna go to the materialized site which I'm already at and then go to components and then forms alright and then down here or somewhere there's a menu this is responsive so I'm gonna no no that's not it I guess it's not we're looking for the file input that's text area select radio buttons checkboxes switches here it is file input so we basically want to just grab this alright so we'll copy that we'll put that right in here and then we want to just add a couple things for the action it's gonna go to slash upload ok and it's gonna be it's gonna have a method of post okay so in our app j/s file we're gonna have to handle a post request to slash upload all right now in this input right here we need to add a name you can call this whatever you want I'm gonna call it my image like that and then let's see I'm also gonna I'm gonna make the upload button grey so I'm just gonna have the class gray to this BTN and then we just need a submit button so let's go down right above the ending form and we're going to put in a button the type of submit give it a class of BTN save and let's reload our app and it should look like this alright now we're gonna need an output for our messages okay we want like file uploaded or if it's an error we want it to output there so right below the h1 ejs works with a syntax like this so an angle bracket and then percentage equals and then we can put basically JavaScript so we're gonna use a shorthand if statement we're gonna use a ternary operator here to see if there's a message variable alright we're gonna see if it's undefined so we're gonna say type of MSG which will be the name of the variable we're gonna say if it's not equals to undefined then okay it's a ternary operator the question mark then we want to display the message if it's not undefined if it is undefined that we want to display nothing okay just quotes and then we'll go ahead and we'll end our ejs statement like that all right so let's save that reload should still work good so now we'll go back to our app dot j s now with multi we need to create a storage engine and we're gonna use something called disk storage which is part of multa so right under where we brought in everything say set storage engine now there's different ways to do different things with multi I'm going to show you what I think is the best way there are I guess you could say easier ways but they're not as I don't know flexible I guess could could be the word it's just harder to to get the results you want like to like to correctly display errors and stuff so I'm gonna give you the kind of the best way to do things so we're gonna create a variable called storage and we're gonna set this tumult err dot disk storage and in here we're gonna pass in an object and then this is going to take in two things a destination so where we want our files uploaded in this case it's gonna be dot slash public slash uploads and then we want to put an ending slash okay next thing we need is file name all right now file name is going to be a function and this function takes in three things it takes in a request the actual file and a callback so what we need to do is we need to call me to call this callback like that and then the first parameter will be an error now we don't want an error so we're gonna say no second is going to be what we want to call this file when it uploads what do we want to name it now you don't want to take its original name because if someone else uploads the file with that name you're going to have issues so there's a lot of different ways you could do this we're gonna first I'm going to show you the easy way which is basically just to add a timestamp on to the filename that way if someone else uploads the same file it'll get renamed to whatever the timestamp is at that time and then we're gonna add an extension onto it like JPEG or PNG whatever it's supposed to be that's that's not the most elegant way if we have time I'll show you a better way but that's what we're gonna do for now so let's say first of all we want to say file dot fieldname I'm sorry I said that wrong I said we were gonna do the original name and then the timestamp we're actually gonna do the field name which is whatever you put here so it'll be my image - and then a timestamp and then the JPEG all right so it's a file dot field name and then we're going to concatenate let's see we're gonna put in here let's do a dash and then I put a dot here I've been working with PHP lately so that's why I just did that so then we're gonna concatenate again the date will say date dot now which will give us the time stamp for right now and then we're gonna add the extension now this is where we use the path module and the path module has a method called ext name or extension name what this does is it takes in a file and it'll extract whatever the extension is whether it's you know JPEG or PNG or whatever so what we want to do is put the original file name in here which we can get from file dot original name so if it's a jpg this will give us JPEG if it's a gif it'll give us gift for whatever and it's gonna add that on to the file name alright so that should be all we need to do right now for this part alright so now that we have our storage engine set we need to initialize the upload variable so we're going to say Const upload and we're going to set this to multi and inside here we're gonna put an object and we're gonna say for the storage we want to use our storage engine okay which is this right here this variable alright and then down here we want to specify dot single because it's a single file you could also do array if you wanted to upload multiple images or files as arrays and then in here it takes the name which in our case is going to be this my image okay so whatever you use there just like that all right well one thing I forgot guys in the in the form here if you're if you're using a file or yeah file upload you need to add an additional attribute to the form tag I forgot all about that so we need to add ink type and that needs to be set to multi-part what is it a multi-part - form what the hell is it I forget hold on a second I should know this multi-part slash form data yeah multi-part slash form - data all right if we don't have that it's not going to work so make sure you put that in alright so now that we have dot single we passed in the field name now we're going to go down to our row which is which we haven't created yet it's going to be a post slash upload alright then we're gonna put an arrow function and make sure we put our request and response now the reason we're using a post is because when we submit the form we're making a post request to slash uploads so that's what we're catching right here so just to make sure it actually submits let's do a res dot send which just sends text to the browser and we'll just say test alright so if we go over here reload and submit we get test which is good all right so now we want to do is we want to call the upload method okay remember how we set up load up here we can actually call that inside of our route now like all right and then in here it's gonna take in request response and then error and we're gonna set that to an arrow function like that all right I'm sorry arrow should actually be should be like that so we have request response and then we have our callback which I'm using an arrow function and that has a parameter of an error so we want to check for the error okay because if there's an error then we wanted to we won't basically want to re-render this template with the message okay remember we have that message output right here so it's gonna look for this msg so what we're gonna do is we're gonna say res render and we're gonna render index should be res and then we're just gonna pass in as the second parameter an object with the message and that message will be the error okay so if there's an error we'll rerender the template we'll pass in the era as the message then we're gonna put an else so L stand for now I just want a console log and we should be able to get the file information through request dot file all right and then I'll just res dot send and we'll just say test so if we upload a file it's just gonna say test in the browser but what we want to do is look down here because we should be logging request dot file and I want to show you what that gives us so let's go ahead and try it we'll grab this image here and submit and you can see what it gives us it gives us the field name which is my image gives us the original name which is this gives us the encoding the mime type which is image slash jpg destination is public uploads we defined that the file name the path and the size okay so it gives us all the stuff that we can use now if you were creating a photo gallery and you connected this to let's say a MongoDB database through Mongoose you could take this information and submit it to a database and then later on you could you know display all the images in your database but we're not we're not going that far we're just doing the upload now if we look in public you can see that it actually got uploaded and if we look at the title of it of the image its my image which is the field name - the time stamp and then JPEG alright and the reason it's named that is because that's what we defined up here in our storage engine so we said use the field name which is my image - there's the - time stamp and then the path alright so you can do you can generate your of your image names however you want this way now let's say we wanted to implement a size limit okay so slide size limit is really easy to implement all we have to do is go down to where we have our upload right here and in addition to storage let's put a comma here and we can say limits set that to an object and we'll say file size and then set that to a number of bytes all right so what I want to set it to is one megabyte which is going to be a million bytes so one two three four five six now just to test it out I'm gonna put ten bytes so let's leave it like that and save and then if if we try to upload something that is not is is larger than this ten bytes which is basically everything then that should invoke this error right here okay we should get this error and it should rerender the template with that message with that error and then we're passing that in as the message alright so hopefully that's clear so I'm gonna just reload this we're gonna click file choose the same image all right so that didn't work see when in that work so it did get uploaded which I didn't want hmm limits files oh you know what this should be a uppercase s I think I did that before too so I'm actually gonna delete both of these images and it'll try that again let's reload this there we go so error file too large and you can see that it did not get uploaded all right now if we want to make it so that we can only upload images that there's a little bit more work than just doing what we did here and let me just reset let me put this to a million bytes all right so right now let's save that let's try to upload a JSON file so we'll submit and you can see that it actually got uploaded over here it got renamed to my imaged timestamp Jason and it's adjacent file but we don't want that to you don't want that to be able to happen so I'm going to delete that and we're gonna go into AB J s let's make this smaller and we're gonna go to our upload and we're gonna put a comma here and then we're gonna say file filter okay and then we're gonna set this to a function and this is gonna take in a request a the file and the callback okay just like just like up here just like the file named it up here and then we it's up to us to do the check so we can either put all the functionality in here or we can create a custom function for this which is what I want to do because I like to keep this this small so we'll create a function called check let's say check file type and then we need to pass into that the file and the callback that comes in from here all right then we'll go down here and we'll create that function so we'll say function check file type takes in the file and the callback all right so there's a there's a couple I mean there's a lot of ways to do this but what I want to do is I want to check not only the extension to make sure it's a dot jpg or a dot PNG but also check the mime type because you can easily rename the extension so I want to check both of those so first thing I'm going to do is create an expression for the file type are the file extensions that I want so let's say aloud extensions we'll create a variable called file types and we're going to set this to an expression so regular expressions we're gonna start and end with a slash and we're gonna say this can be jpg or jpg or PNG or gif or Jif however you want to say it I say gif all right so that's our expression now we want to check the extension so for that we're going to create a variable called ext name extension name we're gonna take that file types and we're gonna call a we're gonna call the javascript function test because we want to basically pass in the extension name of the file and see if it includes any of these alright now we can get the extension name through this file object right here so we can say file actually you know what we want to do the same thing we did up here where we use the path dot txt and then past in the original file name so I'm gonna copy that and put that right in there okay so that's gonna like I said it's going to look at the file the file extension and it's gonna match it to any of these all right we also want to just put this to lowercase so right after this we'll say dot to lowercase like that some parentheses okay then we want to check the mime type so we'll say taunts it's a mime type and we'll set that to file types dot test and then here we just want to pass in file dot mime type okay remember down here when it displayed all that information mime type was one of them all right now the what we just uploaded was a JSON file this was the mime type so that's not gonna match any of this I mean if we put Jason in here that would that would pass but we don't want that we want just images when we uploaded the images the mime type was this image slash J JPEG jpg and that's included in here so that should pass okay hopefully that makes sense now what we want to do is just make sure that both of these extension name and mime type are true so we're gonna do an if and we're gonna say if mime type and ext name so if those are both true then we want to return the call back with null as the error and then just pass true all right else then we want to return the call but all we want to call the call back and we want to put in our error so we're going to say error images only okay so doing it like this calling this callback with the error that's gonna fill this error right here when we actually rerender the template and it's gonna display in the index all right so hopefully that makes sense let's try it out let's save let's go back and let's try to upload first of all the image submit you can see over here it got uploaded let's try to upload the JSON file submit and we get an error images only and it doesn't upload all right so that's what all this did I checked the extension name and check the mime type Jason does not match so we could just got an error okay and you could just as well put all this stuff in here and not you know use a separate function but I think it's cleaner to have this you know have this lighter and not stick all this code in here alright so the next thing we want to do we're just about done the next thing we want to do is just display the image down here after we upload it we don't want to just display tests in the browser so let's go down to our route we're we're doing res dot send test we'll actually get rid of both of these and what we want to do is we want to oh you know what one thing we need to do is make it so that if we don't select a file the form doesn't submit we get an error because right now look I don't select anything and I submit it still works so we need to do that check here so we'll say if requests dot file if request a file is equal to undefined because that's what it'll be if it's not included then we want to res dot render just like this and then we'll pass in for the message we'll say error no file selected okay and then we'll put an else then we want to still render so we'll render the index and then I'm gonna pass in a message of file uploaded and then I'm also gonna send in the actual file so that we can put it into an image tag so we'll save file I'm going to use a why the hell of these back ticks so that we can put a variable in here the location is gonna be in uploads slash and then we'll put in a variable of request dot file dot file name okay file name will give us the final file name that actually was used which would be this in that case ok so let's save it just give it a shot we'll reload this let's try to submit without putting a file in we get no file selected now before the image will actually show we're gonna render it we're gonna pass the image in but we need to put in an image tag for it to display in so we'll go under the form put a line break and then we're going to put in our image tag with a source alright and this is also going to have a class we want it to be responsive we don't want it to go out of its container so we're gonna say class IMG - responsive which is a materialized class now for the source we're going to do kind of what we did with well we are going to do what we did with the message we're going to see if it's undefined so I'll just gonna copy that and put it in so we're gonna say if typeof file is equal to undefined that are not equal to undefined then we want to display file because that's what we passed it in as whoops that's what we passed it in as file so that's what we're looking at so let's save let's refresh this and let's grab an image submit and there we go that doesn't look responsive though is it did I spell it right oh you know what it's responsive image I have it backwards all right so let's try it again I'll submit there we go and we get file uploaded as the message all right so that's gonna be it guys now like I said I am working on a video on how to upload to Amazon s3 we're gonna be using the AWS SDK module and we we will be using multi along with something called multi s3 alright which is a little bit more complicated than doing it you know like this but this is fine if you were to to deploy to like digitalocean or something like that you could you could use this method if you were to push to Heroku though I don't believe you can upload images locally like that you'd have to use something like s3 alright now you guys might want to take this further and create a little photo gallery maybe you know you could you can get all the file information from where is it from the request or from this right here this request dot file and you could stick that in a database and then you could create another route or even use the home route and just do a fetch and display all the images alright so that may be something that you want to do is kind of a little side project but I don't know just giving you some ideas thanks for watching guys please leave a like if you liked this video please subscribe and please follow me on social media if you guys are on Twitter or Instagram or Facebook I do have I always have the links in my description so I would really appreciate it if you guys followed me if you're interested and that's it thanks for watching coding dojo is a programming school that turns beginners into developers and only 14 weeks if you're serious about landing a career in tech black the formal education or background coding dojo will get you there in no time with over 3,000 graduates to date over 90 the grads land jobs within three months of graduating often making over seventy K per year at tech firms of all sizes from companies like Google to local startups to learn more visit coding dojo com or click the link in the description below
Info
Channel: Traversy Media
Views: 210,230
Rating: undefined out of 5
Keywords: node.js, node.js file uploads, node.js image upload, node.js image, node js upload, uploading images with node, multer, node.js multer
Id: 9Qzmri1WaaE
Channel Id: undefined
Length: 37min 10sec (2230 seconds)
Published: Mon Oct 16 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.