AppDividend
Latest Code Tutorials

Angular File Upload Tutorial | Angular Image Upload Example

37

Angular File Upload Tutorial | Angular Image Upload Example. In this example, We will use an ng2-file-upload library to upload a file to the server. We use Node.js as a backend server. We install Angular 6 using Angular CLI and then start working on this Angular File Upload demo. For managing the uploaded files at the backend, we use the multer library. Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on top of busboy for maximum efficiency. Multer will not process any form which is not multipart.

If you want to learn more about Angular then check out this Angular – The complete Guide course.

Angular File Upload Tutorial

We start this project by installing Angular on our machine.

#Step 1: Install Angular 6.

If you have not installed Angular CLI globally on your machine, then 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 that 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, then this package manager is familiar to you. In January 2017 over 350,000 packages were reported being 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 rxjs-compat library.

Since third-party libraries do not support the RxJS 6. Now, one change in Angular 6 is that Angular 6 now depends on TypeScript 2.7 and RxJS 6. So, if you install third-party packages right now, then it is not compatible with Angular 6. In future, all the third-party libraries might upgrade their packages, but right now, it is not compatible with Angular 6.

So, to fill the gap between Angular 6 and third-party packages, we need to install the following library. That is it.

npm install rxjs-compat --save

#Step 4: Install Bootstrap 4.

Go to your terminal and type the following command.

npm install bootstrap --save

After that go to the inside src folder and open styles.css file and import the bootstrap.min.css file.

@import "~bootstrap/dist/css/bootstrap.min.css"

#Step 5: Install 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 which is 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>

 

Angular 6 File Upload Tutorial

#Step 6: 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 essentially 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 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 a 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 7: Run the project.

Start both the server, if not started.

  1. ng server –open
  2. nodemon server

Go to the http://localhost:4200/

Now, until you have not selected any file, the upload an image button will remain disabled.

Upload an image, and see the response you get in the browser console.

Angular Node.js Image Upload

 

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 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. In case 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 the naming conflicts. 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

In an average web app, only dest might be required, and configured as shown in the following example.

let upload = multer({ dest: uploads/ })

If you need more control over your uploads process, you need to use the storage option instead of the dest option. Multer ships with a storage engines DiskStorage and the MemoryStorage; More engines are available from the third parties.

.single(fieldname)

Accept a single file with the name 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 maxCount 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:

[
  { name: avatar, maxCount: 1 },
  { name: gallery, maxCount: 8 }
]

.none()

Accept only text fields. If any file upload is made, 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: Make sure 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 that 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 on storing files to 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 make sure that the directory is created for you.

filename is used to determine what the file should be named inside the folder. If no filename is given, each file will be given a random name that doesn’t include any file extension.

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 might not have been fully populated yet. It depends on the order that 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.

var storage = multer.memoryStorage()
var upload = multer({ storage: storage })

When using memory storage, the file info will contain a field called buffer that contains the entire file.

WARNING: Uploading very large 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 busboy directly, and the details of the properties can be found on 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 which should be 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. 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 by yourself. Also, if you want 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.
  })
})

Finally, Angular File Upload Tutorial With Node | Angular Image Upload Example is over. Thanks for taking.

37 Comments
  1. Brian S says

    Great tutorial. Working perfect.

  2. Troy says

    How to display the images after they are stored

  3. Robin Singh says

    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

  4. Ganesh says

    Is this work in a2hosting or Godaddy server? In the local server it is working fine.

  5. Gopi says

    This is what I am exactly looking for. Got it. Great thanks Krunal.

  6. Nize says

    Thank you so much.

  7. mohan says

    not working for me .anyone please help me
    send me tour code to amohanagarapu@gmail.com

    1. prasanna says

      carefully follow every command, even it didn’t worked for me in the beginning

  8. jaballi aymen says

    thkns for that 🙂
    but how get link this image uplouder!!

    1. bhawna inaniya says

      please perform this operation with form data

  9. bhawna inaniya says

    please send detail about how to add post data with ng2 uploader

  10. Almeida says

    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 🙁

  11. Pankaj Makwana says

    Can you please let me know how to send header with file uploading? I want to send authentication token, and other headers

  12. best iptv says

    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

  13. Mohamed Motyim says

    Thanks a lot this help me

  14. Aditya says

    Getting 404 error while using same with spring rest api on angular 6

  15. Rozy Mahsun says

    How to upload multiple files ?
    Thanks in advanec

  16. Mladen says

    UploadCatalogComponent.html:8 ERROR TypeError: Cannot read property ‘uploadAll’ of undefined

  17. Katheeja says

    has no exported member ‘FileSelectDirective’.Why I get this error?

  18. Katheeja says

    Thanks a lot, How to do file download from server using angular and node.js.Please share snippet.

  19. Katheeja says

    Thanks a lot,upload worked but I am unable to download in original file name. Please help.

  20. Nhi says

    Hi, I have an error: OPTIONS http://localhost:3000/image net:: ERR_CONNECTION_REFUSED
    Please help me. Thanks

  21. jeevanandan says

    I need to send form values also, how can i send?

  22. jk says

    where is the file stored after uploading

  23. jk says

    where is the file stored after uploading

    1. Esteban Potes Rua says

      in the uploads folder

      1. cvvb says

        where is the upload folder

  24. Esteban Potes Rua says

    How to use the download of those files?

  25. Shah Maz says

    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

  26. Nethravathi says

    Can any please help me with the code to upload csv and xlsx file in angular 6?

  27. imran says

    how to upload csv file into mongodb in mean stack angular 7

  28. mounika says

    It’s not working for me can you please any share code.

  29. sathya says

    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.

  30. rgreerre says

    updating image how can it be done

    1. yutu says

      ye i want to know

  31. chaitanya says

    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.

  32. Peters Chikezie says

    Great post. Is there a way to send both and image and other form fields to node server?

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.