Angular File Uploader

Introduction

In my last job I had a task to create a file uploader for an application I was working on. So, I was between using existing libraries or build one from scratch which I opted to do, but why?

From my limited experience in Front-End development, one of the weaknesses I find in JS 3rd party libraries is that they use and depend on many other libraries which put a toll on maintainability and security.

  • How many times we install a library before we get a notification to run audit to address some security concerns?
  • How many times we try to update our libraries then to get hit by a message saying that some libraries can’t be updated because they depend on older versions? or they stop working at all.

In addition, most of the free prebuilt uploaders I found didn’t address the 2 use cases below:

  • Click and Upload
  • Drag and Drop

How to use in your application

The uploader implementation is encapsulated in two folders so lets start by copying them to any place in your project.

  • src > app > uploader: In this folder you can find the complete implementation for the angular uploader.
  • src > app > utilities: This folder contains the implementation for files validation function using IoC/DI pattern. Will explain why and goal later on in this post.

After you finish copying the folders to your project, add UploaderModule to the list of imports in the app-module (or the new parent module for the uploader). Now you are ready to use the uploader in your application….WAIT.. what about the utilities folder?????

Lets spectate the code of utilities > FilesProcessor.ts and explain IoC/DI and how to use/replace it in your code.

export const FILE_PROCESSOR_INJ = new InjectionToken<IFilesProcessor>("File Processor");

export interface IFilesProcessor {
    GetValidFiles(files: File[], filesTypes: string[]): File[];
}

@Injectable()
export class FilesProcessor implements IFilesProcessor {
    constructor() { }

    public GetValidFiles(files: File[], filesTypes: string[]): File[] {
      ....
      ....
      // return valid files;
    }

At first, what is IoC/DI? Lets say it is a way, or a pattern used to separate the definition from its implementation with the goal to minimize and speed up changes to your code–i.e. improve maintainability like bug fixes or changes in logic.

  • IFilesProcessor: Is the definition, which basically an interface that contains the return type and signatures for methods.
  • FilesProcessor: Is the implementation of the definition (IFilesProcessor), which contains the logic of the methods defined in the interface.

In typescript, to use this pattern in your code without using the new keyword is a little different if you are coming from back-end development languages like C# or Java. We need to do few more steps

  1. We need to initialize and export an InjectionToken of type IFileProcessor as we can see in export const FILE_PROCESSOR_INJ = new InjectionToken("File Processor");
  2. We need to specify in our providers in the project module the injectable token FILE_PROCESSOR_INJ and where to find the implementation as we specified in{ provide: FILE_PROCESSOR_INJ, useClass: FilesProcessor }
    • You can replace FileProcessor class with any class you create as long it
      1. Annotated with @Injectable()
      2. Implements the IFileProcessor interface
      3. Replace useClass:FilesProcessor with your new custom class.

Now, everything is set in you project and all what you need is to add the uploader selector to html pages where you want to use it.

<app-file-uploader (UploadsEmitter)="LogFiles($event)" [FileTypes]="['.csv','.jpg']" NumberOfFilesAllowed="3"></app-file-uploader>

You can view a live example of this project and access the repository in the below links.

Demo: https://fileuploader.alwaqfi.net/
Git Repository: https://gitlab.com/alwaqfi/file-uploader-angular

Leave a Reply

Your email address will not be published. Required fields are marked *