File Upload with AngularJS and NodeJS

You are going good with your development work and then you have to do a file upload, oops a hurdle. File upload is not as difficult as some people presume it to be. Well not at-least after this tutorial. Let’s flick the hurdle out of our way.

There are two parts of file upload, the client end where we should enable the user to choose a file and send it to the server. At the server, we receive the file and save it into our desired path.

In this article we will learn to do file upload with angular and node. These can be seen as two separate parts, so for example, if you are working on AngularJS with some other back-end i.e. not Node.js, you can still take help from this article for the angular part of it and vice versa.

Prerequisite

This article assumes you have already worked with AngularJS and Node expressjs and have a basic knowledge of them.

Lets begin

Backend with NodeJS

We will use multer to handle file upload in our express app. Multer is a popular NodeJS middleware package for handling file uploads. Lets have a look at our complete Server file, I’ll explain parts of it later.

Here we are doing two things, we are allowing our express server to accept cross-origin request from another server. (In this case localhost:80)
Alternatively we are asking express to expose client folder as a static path, in this way we can run our AngularJS client code on the same express server (cross-origin wont be required if we follow this).

Here we are defining Multer storage settings. Multer supports two type of storage, viz. memory and disk. We are using diskStorage for this tutorial, as memory storage might give problems if the file is too large or multiple files are uploaded very fast.
In the storage setting we give the destination path to save our files. We also rename our file. I’m appending datetime to the name in order to avoid any duplicate naming conflict. Also we need to append the file extension as by default Multer would save the file without any extension.

Now we create a Multer instance by calling multer and passing our options into it. At the same time we specify the type of upload, that is, if it ismultiple files or single. In our case its single, and the parameter ('file') should normally be the name of the input field in our html form but in our case since we are using ngFileUpload in AngularJS it should match the key which holds the file object in the post request.

Next we create an express route as '/upload' to upload our file. Multer also provides a callback in which we can check if there was an error while performing upload.
Finally we are creating our express server.

File API

Each uploaded file object contains the following information.

file object

Run Express server

To start the express server, go to your working directory in cmd and run node app.js. I’ll also bundle up the gulpfile.js with the downloaded code, so if you use gulp for automation, you can just start the server by running gulp.

This wraps up the work on backend, now lets move to the front-end stuff.

Front-end in AngularJS

We will be using ng-file-upload module in AngularJS for facilitating file uploads.

Setting Up

Along with angular.js we will need to include ng-file-upload related files into our project.
Install ng-file-upload using a package manager or download the required files form here.
Include the files into your project.

Here we have declared our angular app as fileUpload. We are using controller-as syntax ng-controller="MyCtrl as up". Named our form as name="up.upload_form".
Next, we have added an input type as a file, which will allow us to select files. On top of it, we have added a few directives provided by ng-file-upload, explained as followed.

ngf-select

: Shows the type of selection is select. Drag and drop is also available.

ngf-pattern

: Partern to match, type of file.(eg:”‘image/*'” for images)

ngf-max-size

: Maximum file size allowed to be uploaded.

We have also added ng-model as up.file.
Next, we are displaying the thumbnail of the file selected using the ngf-thumbnail directive.
Below which we have added error-validation messages to display. Finally, we have the submit button and we are also showing the upload progress.
At the bottom the libraries are loaded and our angular app file main.js.

Here we have created our app module and defined our controller.
Inject ngFileUpload as a dependency into our app. ngFileUploadprovides an Upload service which we need to inject into our controller. We store the controller instance in vm.vm.submit() is the function called on submit of the form. This function validates the form and in turn calls vm.upload().
The Upload service exposes and upload method, which accepts the web API url and other data. data object should contain the file model to be uploaded. Note the key in the data object that holds the file must match the parameter in your multer’s single file instance.
In our example its file at both places.
We are also calculating and storing the file upload progress in vm.progress variable.

This was it for our client-end implementation, you can run the client app on any localserver or the same express server, see below.

Running our App

Note. These steps may vary if you are not following the same directory structure, ours is as follows, also this structure is only for demonstration purpose, we don’t recommend following it.

Conclusion

Thus we have seen how to upload files using NodeJS and AngularJS. File Upload is not as difficult as some people assume it to be. This was just a basic example of File upload to point you towards the right direction. Also to note, we have learnt file uploads on both ends(back-end and front-end) and the tutorial of each can be used independently of one another. Eg. You can use Multer file upload with some other front-end framework of your choice similarly you can use ngFileUpload with some other back-end technology of your choice. There is a lot more to file uploads like multiple files, drag and drop, etc. You can know more about it by following our reference links below.

Great tutorial. Can I create a new javascript blob/file object and pass it directly without using form data ? What’s the recommended entry point to add this new object ? It’s always
going to be the same file and requires no user interaction.
Thanks

You are welcome dan, is this really what you want? Because the path of the file may differ from client to client and in some cases the file you are looking for would not even exist leading to unnecessary errors.

All the clients are in the same internal private network. The download path will be setup ahead of time and will always be identical for each client workstation, for example http://localhost:3000/uploads/test.txt.
Each day all test.txt files will be used as inputs for further processing. There is no user interface such as
selecting files from an html form. Can I create this javascript object at runtime and insert it after
app.use(bodyParser.json()); and let the rest of the process continue ?
var file = new File([some variable], “test.txt”, { type:”text/plain”, lastModified:date});
Thanks

See, I think you are getting confused here. The path you gave eg: http://localhost:3000/uploads/test.txt this is not a client path it’s rather a path under your express server. Client paths would be something (D://myfiles/myfile.txt).

Dan

|
June 20, 2016 @ 6:44 am

It was a typing mistake on my part. We will go with an html form for user submission.
thanks

thank you sir,its great tutorial, i am done with uploading files but my files are uploaded only in C: drive under uploads folder. how can i give path to my server directory? i want them to be uploaded inside my public directory under uploads folder, so that it will be easy to fetch data.

I am a rookie in these stuffs.
I have to submit similar SPA for an interview assignment, but I am doubtful if using ngFileUpload is if the right way or legit way as I am directly using it as library, will it make any difference to my assesment?
Also I need to save this uploaded images in database someway MongoDB or MYSQL, can you tell me how to do that or approach that ?.
I have to make an Image up loader.

i need small help .while uploading image i need to collect email and name and after uploading into folder i need to store image path,email and name into database .how can i do this please help me out .i am new to this technology

Hi, I keep getting the 413 response. ANy ideas? (Error: request entity too large) The files I am trying to upload are not very big, some even under 1mb. I played around with the bodyparser settings but no luck so far.

It is an amazing tutorial! The only one that I see with complete explanation about it! But I have a doubt… In case of the entire settings equal to the tutorial, what would be the directory structure considering the “uploads” directory? For some reason, although it does not display any errors, the image is simply not written to the uploads directory (in my case, it is at the same level as the client and server directories)

Great tutorial very explanatory, I have hosted my MEAN app on digital ocean I want to upload all product images to server and after upload success I want to get to send back url path with new name to client in angular. Also I want to stor all images to storage provided by digital ocean.

Can you please guide me through how to achieve this? your tutorial is highly appreciated.

Thank you.
You only need to make sure the files you are uploading are publicly available over the web.
Let’s say a static folder, so the path to your uploaded files is yourhost/static, now when you upload the file create a unique name store it into the database and append it to your public URL and send it back. yourhost/static/name-of-file