Angular Bootstrap File Input

Angular File Input - Bootstrap 4 & Material Design

Note: This documentation is for an older version of Bootstrap (v.4). A newer version is available for Bootstrap 5. We recommend migrating to the latest version of our product - Material Design for Bootstrap 5.
Go to docs v.5

Angular Bootstrap's file input is a field that the user can use to upload one or more files (photos, documents or any other file type) from their local storage.

Standard file inputs usually leave a lot to wish for in terms of design, but MDB takes care of that by enhancing them with Material Design best practices.

Most common use examples:

  • CSV upload to CRM system
  • Avatar picture upload
  • Simple GIF upload

Below you can see a number of Angular Bootstrap file inputs created with Material Design for Bootstrap.


Basic example MDB Pro component

Choose file
        
            
          <form>
            <div class="file-field md-form">
              <div mdbBtn color="primary" size="sm" class="waves-light" mdbWavesEffect>
                <span>Choose file</span>
                <input type="file" mdbFileSelect (uploadOutput)="onUploadOutput($event)" [uploadInput]="uploadInput">
              </div>
              <div class="file-path-wrapper">
                <input class="file-path" type="text" placeholder="Upload your file" [value]="showFiles()">
              </div>
            </div>
            <button mdbBtn color="primary" (click)="startUpload()">Start uploading</button>
          </form>
        
        
    
        
            
          import { Component, EventEmitter } from '@angular/core';
          import { UploadFile, UploadInput, UploadOutput } from 'ng-uikit-pro-standard';
          import { humanizeBytes } from 'ng-uikit-pro-standard';

          @Component({
            selector: 'file-input-example',
            templateUrl: 'file-input.html',
          })

          export class FileInputComponent  {
            formData: FormData;
            files: UploadFile[];
            uploadInput: EventEmitter<UploadInput>;
            humanizeBytes: Function;
            dragOver: boolean;

            constructor() {
              this.files = [];
              this.uploadInput = new EventEmitter<UploadInput>();
              this.humanizeBytes = humanizeBytes;
            }

            showFiles() {
              let files = '';
              for (let i = 0; i < this.files.length; i ++) {
                files += this.files[i].name;
                if (!(this.files.length - 1 === i)) {
                  files += ',';
                }
              }
              return files;
            }

            startUpload(): void {
              const event: UploadInput = {
              type: 'uploadAll',
              url: 'your-path-to-backend-endpoint',
              method: 'POST',
              data: { foo: 'bar' },
              };
              this.files = [];
              this.uploadInput.emit(event);
              }

              cancelUpload(id: string): void {
              this.uploadInput.emit({ type: 'cancel', id: id });
            }

            onUploadOutput(output: UploadOutput | any): void {
              if (output.type === 'allAddedToQueue') {
              } else if (output.type === 'addedToQueue') {
                this.files.push(output.file); // add file to array when added
              } else if (output.type === 'uploading') {
                // update current data in files array for uploading file
                const index = this.files.findIndex(file => file.id === output.file.id);
                this.files[index] = output.file;
              } else if (output.type === 'removed') {
                // remove file from array when removed
                this.files = this.files.filter((file: UploadFile) => file !== output.file);
              } else if (output.type === 'dragOver') {
                this.dragOver = true;
              } else if (output.type === 'dragOut') {
              } else if (output.type === 'drop') {
                this.dragOver = false;
              }
              this.showFiles();
            }
          }
        
        
    

File input with floating button MDB Pro component

        
            
          <form>
            <div class="file-field md-form">
              <div mdbBtn floating="true" size="md" color="amber" mdbWavesEffect>
                <mdb-icon fas icon="cloud-upload-alt" aria-hidden="true"></mdb-icon>
                <input type="file" mdbFileSelect (uploadOutput)="onUploadOutput($event)" [uploadInput]="uploadInput">
              </div>
              <div class="file-path-wrapper mt-3">
                <input class="file-path" type="text" placeholder="Upload your file" [value]="showFiles()">
              </div>
            </div>
            <button mdbBtn type="button" color="amber" class="waves-light" (click)="startUpload()" mdbWavesEffect>Start uploading</button>
          </form>
        
        
    
        
            
          import { Component, EventEmitter } from '@angular/core';
          import { UploadFile, UploadInput, UploadOutput } from 'ng-uikit-pro-standard';
          import { humanizeBytes } from 'ng-uikit-pro-standard';

          @Component({
            selector: 'file-input-example',
            templateUrl: 'file-input.html',
          })

          export class FileInputComponent  {
            formData: FormData;
            files: UploadFile[];
            uploadInput: EventEmitter<UploadInput>;
            humanizeBytes: Function;
            dragOver: boolean;

            constructor() {
              this.files = [];
              this.uploadInput = new EventEmitter<UploadInput>();
              this.humanizeBytes = humanizeBytes;
            }

            showFiles() {
              let files = '';
              for (let i = 0; i < this.files.length; i ++) {
                files += this.files[i].name;
                if (!(this.files.length - 1 === i)) {
                  files += ',';
                }
              }
              return files;
            }

            startUpload(): void {
              const event: UploadInput = {
              type: 'uploadAll',
              url: 'your-path-to-backend-endpoint',
              method: 'POST',
              data: { foo: 'bar' },
              };
              this.files = [];
              this.uploadInput.emit(event);
            }

            cancelUpload(id: string): void {
              this.uploadInput.emit({ type: 'cancel', id: id });
            }

            onUploadOutput(output: UploadOutput | any): void {
              if (output.type === 'allAddedToQueue') {
              } else if (output.type === 'addedToQueue') {
                this.files.push(output.file); // add file to array when added
              } else if (output.type === 'uploading') {
                // update current data in files array for uploading file
                const index = this.files.findIndex(file => file.id === output.file.id);
                this.files[index] = output.file;
              } else if (output.type === 'removed') {
                // remove file from array when removed
                this.files = this.files.filter((file: UploadFile) => file !== output.file);
              } else if (output.type === 'dragOver') {
                this.dragOver = true;
              } else if (output.type === 'dragOut') {
              } else if (output.type === 'drop') {
                this.dragOver = false;
              }
              this.showFiles();
            }
          }
        
        
    

File input with gradient floating button MDB Pro component

        
            
          <form>
            <div class="file-field md-form">
              <div mdbBtn floating="true" size="md" gradient="purple" mdbWavesEffect>
                <mdb-icon fas icon="cloud-upload-alt" aria-hidden="true"></mdb-icon>
                <input type="file" mdbFileSelect (uploadOutput)="onUploadOutput($event)" [uploadInput]="uploadInput">
              </div>
              <div class="file-path-wrapper mt-3">
                <input class="file-path" type="text" placeholder="Upload your file" [value]="showFiles()">
              </div>
            </div>
            <button mdbBtn type="button" gradient="purple" class="waves-light" (click)="startUpload()" mdbWavesEffect>Start uploading</button>
          </form>
        
        
    
        
            
          import { Component, EventEmitter } from '@angular/core';
          import { UploadFile, UploadInput, UploadOutput } from 'ng-uikit-pro-standard';
          import { humanizeBytes } from 'ng-uikit-pro-standard';

          @Component({
            selector: 'file-input-example',
            templateUrl: 'file-input.html',
          })

          export class FileInputComponent  {
            formData: FormData;
            files: UploadFile[];
            uploadInput: EventEmitter<UploadInput>;
            humanizeBytes: Function;
            dragOver: boolean;

            constructor() {
              this.files = [];
              this.uploadInput = new EventEmitter<UploadInput>();
              this.humanizeBytes = humanizeBytes;
            }

            showFiles() {
              let files = '';
              for (let i = 0; i < this.files.length; i ++) {
                files += this.files[i].name;
                if (!(this.files.length - 1 === i)) {
                  files += ',';
                }
              }
              return files;
            }

            startUpload(): void {
            const event: UploadInput = {
            type: 'uploadAll',
            url: 'your-path-to-backend-endpoint',
            method: 'POST',
            data: { foo: 'bar' },
            };
            this.files = [];
            this.uploadInput.emit(event);
            }

            cancelUpload(id: string): void {
            this.uploadInput.emit({ type: 'cancel', id: id });
            }

            onUploadOutput(output: UploadOutput | any): void {
              if (output.type === 'allAddedToQueue') {
              } else if (output.type === 'addedToQueue') {
                this.files.push(output.file); // add file to array when added
              } else if (output.type === 'uploading') {
                // update current data in files array for uploading file
                const index = this.files.findIndex(file => file.id === output.file.id);
                this.files[index] = output.file;
              } else if (output.type === 'removed') {
                // remove file from array when removed
                this.files = this.files.filter((file: UploadFile) => file !== output.file);
              } else if (output.type === 'dragOver') {
                this.dragOver = true;
              } else if (output.type === 'dragOut') {
              } else if (output.type === 'drop') {
                this.dragOver = false;
              }
              this.showFiles();
            }
          }
        
        
    

File input with rounded outline button MDB Pro component

        
            
          <form>
            <div class="file-field md-form">
              <div mdbBtn rounded="true" outline="true" color="secondary" size="md" mdbWavesEffect>
                <span class="pt-1">Choose file</span>
                <input type="file" mdbFileSelect (uploadOutput)="onUploadOutput($event)" [uploadInput]="uploadInput">
              </div>
              <div class="file-path-wrapper mt-2">
                <input class="file-path" type="text" placeholder="Upload your file" [value]="showFiles()">
              </div>
            </div>
            <button mdbBtn type="button" rounded="true" outline="true" color="secondary" (click)="startUpload()" mdbWavesEffect>Start uploading</button>
          </form>
        
        
    
        
            
          import { Component, EventEmitter } from '@angular/core';
          import { UploadFile, UploadInput, UploadOutput } from 'ng-uikit-pro-standard';
          import { humanizeBytes } from 'ng-uikit-pro-standard';

          @Component({
            selector: 'file-input-example',
            templateUrl: 'file-input.html',
          })

          export class FileInputComponent  {
            formData: FormData;
            files: UploadFile[];
            uploadInput: EventEmitter<UploadInput>;
            humanizeBytes: Function;
            dragOver: boolean;

            constructor() {
              this.files = [];
              this.uploadInput = new EventEmitter<UploadInput>();
              this.humanizeBytes = humanizeBytes;
            }

            showFiles() {
              let files = '';
              for (let i = 0; i < this.files.length; i ++) {
                files += this.files[i].name;
                if (!(this.files.length - 1 === i)) {
                  files += ',';
                }
              }
              return files;
            }

            startUpload(): void {
              const event: UploadInput = {
              type: 'uploadAll',
              url: 'your-path-to-backend-endpoint',
              method: 'POST',
              data: { foo: 'bar' },
              };
              this.files = [];
              this.uploadInput.emit(event);
              }

              cancelUpload(id: string): void {
              this.uploadInput.emit({ type: 'cancel', id: id });
            }

            onUploadOutput(output: UploadOutput | any): void {
              if (output.type === 'allAddedToQueue') {
              } else if (output.type === 'addedToQueue') {
                this.files.push(output.file); // add file to array when added
              } else if (output.type === 'uploading') {
                // update current data in files array for uploading file
                const index = this.files.findIndex(file => file.id === output.file.id);
                this.files[index] = output.file;
              } else if (output.type === 'removed') {
                // remove file from array when removed
                this.files = this.files.filter((file: UploadFile) => file !== output.file);
              } else if (output.type === 'dragOver') {
                this.dragOver = true;
              } else if (output.type === 'dragOut') {
              } else if (output.type === 'drop') {
                this.dragOver = false;
              }
              this.showFiles();
            }
          }
        
        
    

File input with rounded gradient button MDB Pro component

        
            
          <form>
            <div class="file-field md-form">
              <div mdbBtn rounded="true" gradient="aqua" size="md" mdbWavesEffect>
                <span class="pt-1">Choose file</span>
                <input type="file" mdbFileSelect (uploadOutput)="onUploadOutput($event)" [uploadInput]="uploadInput">
              </div>
              <div class="file-path-wrapper mt-2">
                <input class="file-path" type="text" placeholder="Upload your file" [value]="showFiles()">
              </div>
            </div>
            <button mdbBtn type="button" rounded="true" gradient="aqua" (click)="startUpload()" mdbWavesEffect>Start uploading</button>
          </form>
        
        
    
        
            
          import { Component, EventEmitter } from '@angular/core';
          import { UploadFile, UploadInput, UploadOutput } from 'ng-uikit-pro-standard';
          import { humanizeBytes } from 'ng-uikit-pro-standard';

          @Component({
            selector: 'file-input-example',
            templateUrl: 'file-input.html',
          })

          export class FileInputComponent  {
            formData: FormData;
            files: UploadFile[];
            uploadInput: EventEmitter<UploadInput>;
            humanizeBytes: Function;
            dragOver: boolean;

            constructor() {
              this.files = [];
              this.uploadInput = new EventEmitter<UploadInput>();
              this.humanizeBytes = humanizeBytes;
            }

            showFiles() {
              let files = '';
              for (let i = 0; i < this.files.length; i ++) {
                files += this.files[i].name;
                if (!(this.files.length - 1 === i)) {
                  files += ',';
                }
              }
              return files;
            }

            startUpload(): void {
              const event: UploadInput = {
              type: 'uploadAll',
              url: 'your-path-to-backend-endpoint',
              method: 'POST',
              data: { foo: 'bar' },
              };
              this.files = [];
              this.uploadInput.emit(event);
            }

            cancelUpload(id: string): void {
              this.uploadInput.emit({ type: 'cancel', id: id });
            }

            onUploadOutput(output: UploadOutput | any): void {
              if (output.type === 'allAddedToQueue') {
              } else if (output.type === 'addedToQueue') {
                this.files.push(output.file); // add file to array when added
              } else if (output.type === 'uploading') {
                // update current data in files array for uploading file
                const index = this.files.findIndex(file => file.id === output.file.id);
                this.files[index] = output.file;
              } else if (output.type === 'removed') {
                // remove file from array when removed
                this.files = this.files.filter((file: UploadFile) => file !== output.file);
              } else if (output.type === 'dragOver') {
                this.dragOver = true;
              } else if (output.type === 'dragOut') {
              } else if (output.type === 'drop') {
                this.dragOver = false;
              }
              this.showFiles();
            }
          }
        
        
    

Removing files from file upload queue MDB Pro component

Use the removeFile(id: string) method to remove specific file from upload queue. Use the this.files[index].id property as an method argument.

        
            
            <form>
              <div class="file-field md-form">
                <div mdbBtn rounded="true" gradient="aqua" size="md" mdbWavesEffect>
                  <span class="pt-1">Choose file</span>
                  <input type="file" mdbFileSelect (uploadOutput)="onUploadOutput($event)" [uploadInput]="uploadInput">
                </div>
                <div class="file-path-wrapper mt-2">
                  <input class="file-path" type="text" placeholder="Upload your file" [value]="showFiles()">
                </div>
              </div>
              <button mdbBtn type="button" rounded="true" gradient="aqua" (click)="startUpload()" mdbWavesEffect>Start uploading
              </button>
              <button mdbBtn type="button" rounded="true" gradient="aqua" (click)="removeFirstFileFromQueue()" mdbWavesEffect>Remove
                file from queue
              </button>
            </form>
          
        
    
        
            
            import { Component, EventEmitter } from '@angular/core';
            import { UploadFile, UploadInput, UploadOutput } from 'ng-uikit-pro-standard';
            import { humanizeBytes } from 'ng-uikit-pro-standard';

            @Component({
              selector: 'file-input-example',
              templateUrl: 'file-input.html',
            })
            export class FileInputComponent {
              formData: FormData;
              files: UploadFile[];
              uploadInput: EventEmitter<UploadInput>;
              humanizeBytes: Function;
              dragOver: boolean;

              constructor() {
                this.files = [];
                this.uploadInput = new EventEmitter < UploadInput > ();
                this.humanizeBytes = humanizeBytes;
              }

              showFiles() {
                let files = '';
                for (let i = 0; i < this.files.length; i++) {
                  files += this.files[i].name;
                  if (!(this.files.length - 1 === i)) {
                    files += ',';
                  }
                }
                return files;
              }

              startUpload(): void {
                const event: UploadInput = {
                  type: 'uploadAll',
                  url: 'your-path-to-backend-endpoint',
                  method: 'POST',
                  data: { foo: 'bar' },
                };
                this.removeFirstFileFromQueue();
                this.files = [];
                this.uploadInput.emit(event);
              }

              cancelUpload(id: string): void {
                this.uploadInput.emit({ type: 'cancel', id: id });
              }

              onUploadOutput(output: UploadOutput | any): void {
                if (output.type === 'allAddedToQueue') {
                } else if (output.type === 'addedToQueue') {
                  this.files.push(output.file); // add file to array when added
                } else if (output.type === 'uploading') {
                  // update current data in files array for uploading file
                  const index = this.files.findIndex(file => file.id === output.file.id);
                  this.files[index] = output.file;
                } else if (output.type === 'removed') {
                  // remove file from array when removed
                  this.files = this.files.filter((file: UploadFile) => file !== output.file);
                } else if (output.type === 'dragOver') {
                  this.dragOver = true;
                } else if (output.type === 'dragOut') {
                } else if (output.type === 'drop') {
                  this.dragOver = false;
                }
                this.showFiles();
              }

              removeFile(id: string): void {
                this.uploadInput.emit({ type: 'remove', id: id });
              }

              removeFirstFileFromQueue() {
                this.removeFile(this.files[0].id);
              }
            }
          
        
    

Using upload options MDB Pro component

        
            
            <form>
              <div class="file-field md-form">
                <div mdbBtn color="primary" size="sm" class="waves-light" mdbWavesEffect>
                  <span>Choose file</span>
                  <input type="file" mdbFileSelect [options]="options" (uploadOutput)="onUploadOutput($event)" [uploadInput]="uploadInput">
                </div>
                <div class="file-path-wrapper">
                  <input class="file-path" type="text" placeholder="Upload your file" [value]="showFiles()">
                </div>
              </div>
              <button mdbBtn color="primary" (click)="startUpload()">Start uploading</button>
            </form>
          
        
    
        
            
            import { Component, EventEmitter } from '@angular/core';
            import { UploadFile, UploadInput, UploadOutput, UploaderOptions } from 'ng-uikit-pro-standard';
            import { humanizeBytes } from 'ng-uikit-pro-standard';

            @Component({
              selector: 'file-input-example',
              templateUrl: 'file-input.html',
            })

            export class FileInputComponent {
              formData: FormData;
              files: UploadFile[];
              uploadInput: EventEmitter<UploadInput>;
              humanizeBytes: Function;
              dragOver: boolean;
              options: UploaderOptions

              constructor() {
                this.options = {
                  concurrency: 1,
                  maxUploads: 2,
                  allowedContentTypes: ['text/plain']
                };
                this.files = [];
                this.uploadInput = new EventEmitter < UploadInput > ();
                this.humanizeBytes = humanizeBytes;
              }

              showFiles() {
                let files = '';
                for (let i = 0; i < this.files.length; i++) {
                  files += this.files[i].name;
                  if (!(this.files.length - 1 === i)) {
                    files += ',';
                  }
                }
                return files;
              }

              startUpload(): void {
                const event: UploadInput = {
                  type: 'uploadAll',
                  url: 'your-path-to-backend-endpoint',
                  method: 'POST',
                  data: { foo: 'bar' },
                };
                this.files = [];
                this.uploadInput.emit(event);
              }

              cancelUpload(id: string): void {
                this.uploadInput.emit({ type: 'cancel', id: id });
              }

              onUploadOutput(output: UploadOutput | any): void {
                if (output.type === 'allAddedToQueue') {
                } else if (output.type === 'addedToQueue') {
                  this.files.push(output.file); // add file to array when added
                } else if (output.type === 'uploading') {
                  // update current data in files array for uploading file
                  const index = this.files.findIndex(file => file.id === output.file.id);
                  this.files[index] = output.file;
                } else if (output.type === 'removed') {
                  // remove file from array when removed
                  this.files = this.files.filter((file: UploadFile) => file !== output.file);
                } else if (output.type === 'dragOver') {
                  this.dragOver = true;
                } else if (output.type === 'dragOut') {
                } else if (output.type === 'drop') {
                  this.dragOver = false;
                }
                this.showFiles();
              }
            }
          
        
    

Angular File Input - API

In this section you will find informations about required modules of file input component.


Modules used

In order to speed up your application, you can choose to import only the modules you actually need, instead of importing the entire MDB Angular library. Remember that importing the entire library, and immediately afterwards a specific module, is bad practice, and can cause application errors.

        
            
            import { FileInputModule, WavesModule } from 'ng-uikit-pro-standard';
          
        
    

Directives

MdbFileSelect

Selector: mdbFileSelect

Type: MDBFileSelectDirective

MdbFileDrop

Selector: mdbFileDrop

Type: MDBFileDropDirective


Inputs

Name Type Default Description Example
options UploaderOptions - Allow to specify custom upload options [options] = { concurrency: 1, maxUploads: 1, allowedContentTypes: ['text/plain', 'image/jpeg', 'image/png'] };
Uploader options

Custom upload options

Name Type Description
allowedContentTypes string[] Allowed types of uploaded files
concurrency number Number of files uploaded at the same time
maxUploads number Max number of files that can be uploaded

Angular File Input - examples & customization


Uploading file with File Input MDB Pro component

In order to show how to send a file through the File Input component, you need to set up a server. We will use Node + Express.js stack.

If you come across a problem, please check our support forum to see if someone else has already had a similar problem. If not, then feel free to set up a new topic!

The whole project is available at this address as a zip archive.

As a first step, copy the following HTML and TS code into your project.

        
            
          <form>
            <div class="file-field md-form d-flex justify-content-between align-items-center">
              <div mdbBtn floating="true" size="md" color="amber" mdbWavesEffect>
                <mdb-icon fas icon="cloud-upload-alt" aria-hidden="true"></mdb-icon>
                <input type="file" mdbFileSelect (uploadOutput)="onUploadOutput($event)" [uploadInput]="uploadInput">
              </div>
              <div class="file-path-wrapper mt-1">
                <input class="file-path" type="text" placeholder="Upload your file" [value]="showFiles()">
              </div>
              <button mdbBtn type="button" size="sm" color="amber" rounded="true" class="darken-2 waves-light" (click)="startUpload()"
                mdbWavesEffect>Start
                uploading</button>
            </div>
          </form>
        
        
    
        
            
          import { Component, EventEmitter } from '@angular/core';
          import { UploadInput, UploadOutput, UploadFile, humanizeBytes } from 'ng-uikit-pro-standard';

          @Component({
            selector: 'app-root',
            templateUrl: './app.component.html',
            styleUrls: ['./app.component.scss']
          })
          export class AppComponent {
            formData: FormData;
            files: UploadFile[];
            uploadInput: EventEmitter<UploadInput>;
            humanizeBytes: Function;
            dragOver: boolean;

            constructor() {
              this.files = [];
              this.uploadInput = new EventEmitter<UploadInput>();
              this.humanizeBytes = humanizeBytes;
            }

            showFiles() {
              let files = '';
              for (let i = 0; i < this.files.length; i ++) {
                files += this.files[i].name;
                if (!(this.files.length - 1 === i)) {
                  files += ',';
                }
              }
              return files;
            }

            startUpload(): void {
              const event: UploadInput = {
              type: 'uploadAll',
              url: 'http://localhost:3001/api/upload',
              method: 'POST',
              data: { foo: 'bar' },
              };
              this.files = [];
              this.uploadInput.emit(event);
            }

            cancelUpload(id: string): void {
              this.uploadInput.emit({ type: 'cancel', id: id });
            }

            onUploadOutput(output: UploadOutput | any): void {
              if (output.type === 'allAddedToQueue') {
              } else if (output.type === 'addedToQueue') {
                this.files.push(output.file); // add file to array when added
              } else if (output.type === 'uploading') {
                // update current data in files array for uploading file
                const index = this.files.findIndex(file => file.id === output.file.id);
                this.files[index] = output.file;
              } else if (output.type === 'removed') {
                // remove file from array when removed
                this.files = this.files.filter((file: UploadFile) => file !== output.file);
              } else if (output.type === 'dragOver') {
                this.dragOver = true;
              } else if (output.type === 'dragOut') {
              } else if (output.type === 'drop') {
                this.dragOver = false;
              }
              this.showFiles();
            }
          }
        
        
    

Necessary files and folders

In the next step in your application's root directory, create the following folders and the files that they will contain.

  • bin/www.ts,
  • routes/index.ts,
  • uploads,
  • app.ts.
File upload files structure

Necessary libraries and filling up files

The next step is to install the following additional libraries, thanks to which we will handle the sending of the file to the backend, and then complete the previously created files with the required code.

        
            
          npm install --save express body-parser cors multer
        
        
    

Copy the below code into app.ts file

        
            
          const express = require('express');
          const path = require('path');
          const bodyParser = require('body-parser');
          const cors = require('cors');

          const indexRouter = require('./routes/index');
          const app = express();

          const corsOptions = {
            origin: '*',
            optionsSuccessStatus: 200
          };

          app.use(cors(corsOptions));
          app.use(bodyParser.json());
          app.use(bodyParser.urlencoded({ extended: true }));

          // create a cors middleware
          app.use((req, res, next) => {
            // set headers to allow cross origin request.
            res.header('Access-Control-Allow-Origin', '*');
            res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
            res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
            next();
          });

          app.use('/api', indexRouter);

          module.exports = app;
        
        
    

Then copy the below code into routes/index.ts file

        
            
          const exp = require('express');
          const router = exp.Router();
          const multer = require('multer');
          const DIR = './uploads/';

          let upload = multer({ dest: DIR }).single('file');

          router.post('/upload', (req, res, next) => {
            let path = '';
            upload(req, res, (err) => {
                if (err) {
                    console.log(err);
                    return res.status(422).send('An error occured');
                }
                path = req.file.path;
                console.log('Uploaded');
                return res.send('Upload completed for ' + path);
            });
          });

          module.exports = router;
        
        
    

And the last .ts file which you have to fill up is bin/www.ts file.

        
            
          #!/usr/bin/env node

          /**
          * Module dependencies.
          */

          const appFile = require('../app');
          const debug = require('debug')('file-upload:server');
          const http = require('http');

          /**
          * Get port from environment and store in Express.
          */

          const port = normalizePort(process.env.PORT || '3001');
          appFile.set('port', port);

          /**
          * Create HTTP server.
          */

          const server = http.createServer(appFile);

          /**
          * Listen on provided port, on all network interfaces.
          */

          server.listen(port);
          server.on('error', onError);
          server.on('listening', onListening);

          /**
          * Normalize a port into a number, string, or false.
          */

          function normalizePort(val) {
            const portNumber = parseInt(val, 10);

            if (isNaN(portNumber)) {
            // named pipe
            return val;
            }

            if (portNumber >= 0) {
            // port number
            return portNumber;
            }

            return false;
          }

          /**
          * Event listener for HTTP server "error" event.
          */

          function onError(error) {
          if (error.syscall !== 'listen') {
            throw error;
          }

          const bind = typeof port === 'string' ?
          'Pipe ' + port :
          'Port ' + port;

          // handle specific listen errors with friendly messages
          switch (error.code) {
            case 'EACCES':
            console.error(bind + ' requires elevated privileges');
            process.exit(1);
            break;
            case 'EADDRINUSE':
            console.error(bind + ' is already in use');
            process.exit(1);
            break;
            default:
            throw error;
          }
          }

          /**
          * Event listener for HTTP server "listening" event.
          */

          function onListening() {
            const addr = server.address();
            const bind = typeof addr === 'string' ?
            'pipe ' + addr :
            'port ' + addr.port;
            debug('Listening on ' + bind);
          }
        
        
    

After you have completed all required files with the above code, add a script to the package.json file, which will run your server.

        
            
          "server": "tsc app.ts && tsc routes/index.ts && tsc bin/www.ts && node ./bin/www.js"
        
        
    

Running the server and testing file upload

At the very end, we have nothing left to do but to run the server and the application. To do this, open two terminal windows, and run the commands npm run server and ng serve in them.

        
            
          npm run server
        
        
    
        
            
          ng serve
        
        
    

Conclusion

The above commands will run two processes - one responsible for server operation and the other for Angular application operation. Now it is enough to select a file and press the Upload button, and after a while, this file will be in your project, in the uploads directory. The name of this file is hashed, so you can avoid duplicate files.

Important note

Please note that a piece of CORS-enabled code is only placed in the development environment. It is not recommended to use this piece of code in a production environment unless you know what you are doing.