In this example, we will use Node.js as a backend server. So first, we install Angular using Angular CLI and then start working on this Angular file upload demo.
Angular file upload
To upload files in Angular, use the ng2-file-upload library. For managing the uploaded files at the backend, we use the multer library. Multer is a node.js middleware for handling multipart/form-data, primarily used for uploading files. It is written on top of the busboy for maximum efficiency. Therefore, Multer will not process any form which is not multipart.
To upload from scratch, follow the below steps. But, first, we start this project by installing Angular on our machine.
Step 1: Install Angular.
If you have not installed Angular CLI globally on your machine, install it using the following command. We are using NPM as a package manager for JS development.
Today NPM is the biggest repository for any programming language, and it has almost every package you need in a web or mobile development project. npm means the node package manager. If you have previous work with any front-end development stuff, this package manager is familiar.
In January 2020, over 700,000 packages were reported to be listed in the npm registry, making it the most significant single language code repository on the planet.
npm install -g @angular/cli # or yarn add global @angular/cli
Now, create a local project using the following command.
ng new fileupload
Now, start the application using the following command.
ng serve --open
Step 2: Install the rxjs-compat library.
Since third-party libraries do not support the RxJS, one change in Angular now depends on the latest TypeScript and RxJS versions. So, if you install third-party packages right now, it is not compatible with Angular.
In the future, all third-party libraries might upgrade their packages, but it is not compatible with Angular.
So, to fill the gap between Angular and third-party packages, we need to install the following library. That is it.
npm install rxjs-compat --save
Step 3: Install Bootstrap 4.
Go to your terminal and type the following command.
npm install bootstrap --save
After that, go to the inside src folder, open the styles.css file, and import the bootstrap.min.css file.
@import "~bootstrap/dist/css/bootstrap.min.css"
Step 4: Install the ng-file-upload library.
Type the following command to install the library.
npm install ng2-file-upload --save
Now, write the following code inside an app.module.ts file.
// app.module.ts import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FileSelectDirective } from 'ng2-file-upload'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent, FileSelectDirective ], imports: [ BrowserModule, FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
We are using Angular Forms, the package included in Angular by default project.
Okay, so we have imported FormsModule and FileSelectDirective.
Now, write the following code inside an app.component.ts file.
// app.component.ts import { Component, OnInit } from '@angular/core'; import { FileUploader, FileSelectDirective } from 'ng2-file-upload/ng2-file-upload'; const URL = 'http://localhost:3000/api/upload'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'app'; public uploader: FileUploader = new FileUploader({url: URL, itemAlias: 'photo'}); ngOnInit() { this.uploader.onAfterAddingFile = (file) => { file.withCredentials = false; }; this.uploader.onCompleteItem = (item: any, response: any, status: any, headers: any) => { console.log('ImageUpload:uploaded:', item, status, response); alert('File uploaded successfully'); }; } }
Finally, write the following code inside an app.component.html file.
<input type="file" name="photo" ng2FileSelect [uploader]="uploader" /> <button type="button" class="btn btn-success btn-s" (click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length" > Upload an Image </button>
Step 5: Create Node.js backend.
First, install the following node modules.
npm install express multer body-parser --save
We have installed Express as a web framework for Node.js development.
Install nodemon as a dev dependency.
npm install nodemon --save-dev
Create a new directory inside root called uploads.
Okay, now create one file in the project root folder called server.js.
// server.js const path = require('path'); const fs = require('fs'); const express = require('express'); const multer = require('multer'); const bodyParser = require('body-parser') const app = express(); const router = express.Router(); const DIR = './uploads'; let storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, DIR); }, filename: (req, file, cb) => { cb(null, file.fieldname + '-' + Date.now() + '.' + path.extname(file.originalname)); } }); let upload = multer({storage: storage}); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.use(function (req, res, next) { res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200'); res.setHeader('Access-Control-Allow-Methods', 'POST'); res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); res.setHeader('Access-Control-Allow-Credentials', true); next(); }); app.get('/api', function (req, res) { res.end('file catcher example'); }); app.post('/api/upload',upload.single('photo'), function (req, res) { if (!req.file) { console.log("No file received"); return res.send({ success: false }); } else { console.log('file received'); return res.send({ success: true }) } }); const PORT = process.env.PORT || 3000; app.listen(PORT, function () { console.log('Node.js server is running on port ' + PORT); });
In the above code, we have defined the express router. Routing refers to how an application’s endpoints (URIs) respond to client requests.
The Express Router class helps in the creation of route handlers.
Express apps utilize routers that are necessarily containers for a set of middleware. We can put this middleware holder only on a specific route, which allows us to keep our logic in separate files and bring them together on our terms.
So, I have used a multer module to store the file.
Multer adds the body object and the file or files object to a request object. The body object contains the values of text fields of a form; a file or files object contains the files uploaded via the HTML form. Don’t forget the enctype=”multipart/form-data” in your HTML form.
Now, boot up the server using the following command.
nodemon server
Step 6: Run the project.
Start both the server, if not started.
- ng server –open
- nodemon server
Go to the http://localhost:4200/
Until you have selected any file, the upload an image button will remain disabled.
Upload an image, and see the response you get in the browser console.
I have also written an Angular 8 Image Upload Example in this blog.
You can modify and resize the image on the node.js backend as well. I have also written a tutorial on resizing image using node.js and Express.
Multer API
File information
Each file contains the following information:
Key | Description | Note |
---|---|---|
fieldname |
Field name specified in the form | |
originalname |
Name of a file on the user’s computer | |
encoding |
Encoding type of the file | |
mimetype |
The mime type of the file | |
size |
Size of the file in bytes | |
destination |
The folder to which a file has been saved | DiskStorage |
filename |
The name of the file within the destination |
DiskStorage |
path |
The full path to the uploaded file | DiskStorage |
buffer |
A Buffer of the entire file |
MemoryStorage |
#multer(opts)
Multer accepts the options object, the most basic of which is a dest property, which tells Multer where to upload the files on the server. If you omit the options object, the files will be kept in the memory and never written on the disk.
By default, Multer will rename the files to avoid naming conflicts. However, the renaming function can be modified according to your needs.
The following are the main options that can be passed to Multer.
Key | Description |
---|---|
dest or storage |
Where to store the files |
fileFilter |
Function to control which files are accepted |
limits |
Limits of the uploaded data |
preservePath |
Keep the full path of the files instead of just a base name |
An average web app might only be required and configured, as shown in the following example.
If you need more control over your uploads process, you need to use the storage option instead of the dest option
. Multer ships with storage engines DiskStorage
and the MemoryStorage
; More engines are available from third parties.
.single(fieldname)
Accept a single file with the name called fieldname
. The single file will be stored in req.file
.
.array(fieldname[, maxCount])
Accept the array of files, all with the name fieldname
. Optionally error out if more than files are uploaded. An array of files will be stored in req.files
.
.fields(fields)
Accept a mix of files, specified by fields
. An object with arrays of files will be stored in req.files
.
fields
should be an array of objects with name
and optionally a maxCount
. Example:
.none()
Accept only text fields. If any file upload is made, an error with code “LIMIT_UNEXPECTED_FILE” will be issued.
.any()
Accepts all files that come over the wire. An array of files will be stored in req.files
.
WARNING: Ensure that you always handle the files that a user uploads. Never add multer as a global middleware since a malicious user could upload files to a route you didn’t anticipate. Only use this function on routes where you are handling the uploaded files.
storage
DiskStorage
The disk storage engine gives you full control over storing files on a disk.
// server.js let storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, '/tmp/my-uploads') }, filename: function (req, file, cb) { cb(null, file.fieldname + '-' + Date.now()) } }) let upload = multer({ storage: storage })
There are two options available, destination
and filename
. They are both functions that determine where the file should be stored.
destination
is used to determine within which folder the uploaded files should be stored. This can also be given as a string
(e.g. '/tmp/uploads'
). If no destination
is given, the operating system’s default directory for temporary files is used.
Note: You are responsible for creating the directory when providing a destination as a function. When passing a string, multer will ensure that the directory is created for you.
filename
is used to determine what the file should be named inside the folder. Each file will be given a random name that doesn’t include any file extension if no one is given.
Note: Multer will not append any file extension for you; your function should return a filename complete with a file extension.
Each function gets passed both the request (req
) and some information about the file (file
) to aid with the decision.
Note that req.body
It might not have been fully populated yet. It depends on how the client transmits fields and files to the server.
#MemoryStorage
The memory storage engine stores the files in memory as Buffer
objects. It doesn’t have any options.
When using memory storage, the file info will contain a field called buffer
that includes the entire file.
WARNING: Uploading huge files, or relatively small files in large numbers very quickly, can cause your application to run out of memory when memory storage is used.
#limits
An object specifying the size limits of the following optional properties. Multer passes this object into the busboy directly, and the details of the properties can be found on the busboy’s page.
The following integer values are available:
Key | Description | Default |
---|---|---|
fieldNameSize |
Max field name size | 100 bytes |
fieldSize |
Max field value size | 1MB |
fields |
Max number of non-file fields | Infinity |
fileSize |
For multipart forms, the max file size (in bytes) | Infinity |
files |
For multipart forms, the max number of file fields | Infinity |
parts |
For multipart forms, the max number of parts (fields + files) | Infinity |
headerPairs |
For multipart forms, the max number of header key=>value pairs to parse | 2000 |
Specifying the limits can help protect your site against denial of service (DoS) attacks.
#fileFilter
Set this to a function to control which files should be uploaded and skipped. The function should look like this:
// server.js function fileFilter (req, file, cb) { // The function should call `cb` with a boolean // to indicate if the file should be accepted // To reject this file pass `false`, like so: cb(null, false) // To accept the file pass `true`, like so: cb(null, true) // You can always pass an error if something goes wrong: cb(new Error('I don\'t have a clue!')) }
#Error handling
When encountering an error, Multer will delegate the error to Express. Thus, you can display a nice error page using the standard expressway.
If you want to catch errors specifically from Multer, you can call the middleware function yourself. Also, if you’re going to catch only the Multer errors, you can use the MulterError class that is attached to the multer object itself (e.g. err instanceof multer.MulterError
).
// server.js var multer = require('multer') var upload = multer().single('avatar') app.post('/profile', function (req, res) { upload(req, res, function (err) { if (err instanceof multer.MulterError) { // A Multer error occurred when uploading. } else if (err) { // An unknown error occurred when uploading. } // Everything went fine. }) })
That’s it for this tutorial. Thanks for taking it.
Great tutorial. Working perfect.
How to display the images after they are stored
I watched many tutorials but u r the best.
i m trying from last 2 weeks but nothing happens. Thanku for this tutorial.
Can u make a new tutorial on how to show image after save in folder and database
Is this work in a2hosting or Godaddy server? In the local server it is working fine.
This is what I am exactly looking for. Got it. Great thanks Krunal.
Thank you so much.
not working for me .anyone please help me
send me tour code to amohanagarapu@gmail.com
carefully follow every command, even it didn’t worked for me in the beginning
thkns for that 🙂
but how get link this image uplouder!!
please perform this operation with form data
please send detail about how to add post data with ng2 uploader
How can I show the image that was uploaded? To upload an image is easy, but I don`t get how can I fetch it and show it 🙁
Can you please let me know how to send header with file uploading? I want to send authentication token, and other headers
bonjour
great share.
I think the most stable premium iptv servers are those from Fishbone IPTV cloud
I would like to see more posts like this
Thanks
Thanks a lot this help me
Getting 404 error while using same with spring rest api on angular 6
How to upload multiple files ?
Thanks in advanec
UploadCatalogComponent.html:8 ERROR TypeError: Cannot read property ‘uploadAll’ of undefined
has no exported member ‘FileSelectDirective’.Why I get this error?
Thanks a lot, How to do file download from server using angular and node.js.Please share snippet.
Thanks a lot,upload worked but I am unable to download in original file name. Please help.
Hi, I have an error: OPTIONS http://localhost:3000/image net:: ERR_CONNECTION_REFUSED
Please help me. Thanks
I need to send form values also, how can i send?
where is the file stored after uploading
where is the file stored after uploading
in the uploads folder
where is the upload folder
How to use the download of those files?
I got another issue. after running server.js upload works perfect but I got 404 Err ‘File NOT found’ from another method I already have.
this.httpClnt.get (‘assets/daily.json’); //it works before running server.js but after running httpClient Get json files not working
any idea
Can any please help me with the code to upload csv and xlsx file in angular 6?
how to upload csv file into mongodb in mean stack angular 7
It’s not working for me can you please any share code.
It’s working fine up to UI but it’s not working in services part for me
Ex: in my project i am getting service path http://localhost:3000/api/upload always not found 404 error
Can you please any one help me for this.
updating image how can it be done
ye i want to know
ng build –prod getting error:
Please consider moving FileSelectDirective in node_modules/ng2-file-upload/file-upload/file-select.directive.d.ts to a higher module that imports AppModule in src/app/app.module.ts and FileUploadModule in node_modules/ng2-file-upload/file-upload/file-upload.module.d.ts. You can also create a new NgModule that exports and includes FileSelectDirective in node_modules/ng2-file-upload/file-upload/file-select.directive.d.ts then import that NgModule in AppModule in src/app/app.module.ts and FileUploadModule in node_modules/ng2-file-upload/file-upload/file-upload.module.d.ts.
Great post. Is there a way to send both and image and other form fields to node server?
Can upload video using file upload?