top of page

How to Upload a File Image with Angular



File or Image upload is an essential component to make a form that stores some image kind of data. It helps in applications using image upload or in file sharing. This file-upload component uses file.io API for uploading a file and in return, it provides a shareable link. Furthermore, we can send get request to a shareable link to get the file but for now, our only focus is on the upload section so we only use the post method.


In this article, we will learn how to upload a file image with Angular:


1. Create a template

We will create a reusable, easily pluggable component into other components. Let’s start with a simple HTML template for our input.

<label class="image-upload-container btn btn-bwm">
<span>Select Image</span>
<input #imageInput
         type="file"
         accept="image/*"(change)="processFile(imageInput)">
</label>

The Accept attribute defines accepted files for input. Image/* specifies that we can choose images of any type by this input. #imageInput is a reference of input on which we can access uploaded files. A Change event is fired when we select a file.


2. Component Code

class ImageSnippet 
{
  constructor(public src: string, public file: File) {}
}

@Component({
  selector: 'bwm-image-upload',
  templateUrl: 'image-upload.component.html',
  styleUrls: ['image-upload.component.scss']})export class ImageUploadComponent {

  selectedFile: ImageSnippet;
  constructor(private imageService: ImageService){}
  processFile(imageInput: any) 
  {
    const file: File = imageInput.files[0];
    const reader = new FileReader();

    reader.addEventListener('load', (event: any) => 
    {
      this.selectedFile = new ImageSnippet(event.target.result, file);
      this.imageService.uploadImage(
          this.selectedFile.file).subscribe((res) => {},(err) => {})});

    reader.readAsDataURL(file);
    }
}

In processFile we are getting an image input we sent from the change event. By writing imageInput.files[0] we are accessing the first file. We need a reader in order to access additional properties of a file. By calling readAsDataURL, we can get a base64 representation of an image in the callback function of the addEventListener we subscribed to before.


In a callback function, we are creating an instance of the ImageSnippet. The first value is a base64 representation of an image we will display later on the screen. The second value is the file itself, which we will send to the server for upload to Amazon S3.


3. Create Service code

The service will be the one responsible for sending a request to our Node server.

export class ImageService 
{
    constructor(private http: Http) {}
    public uploadImage(image: File): Observable<Response> 
    {
        const formData = new FormData();

    formData.append('image', image);
    return this.http.post('/api/v1/image-upload', formData);
    }
}

We need to send an image in the form data. We will append the image under the key of an image to form data (same key we configured before in Node). Finally, we just need to send a request to the server with formData in a payload.


4.UX Updates

class ImageSnippet {
  pending: boolean = false;
  status: string = 'init';
  constructor(public src: string, public file: File) {}
}

@Component({
  selector: 'bwm-image-upload',
  templateUrl: 'image-upload.component.html',
  styleUrls: ['image-upload.component.scss']})export class ImageUploadComponent {

  selectedFile: ImageSnippet;
  constructor(private imageService: ImageService){}
  private onSuccess() 
  {
    this.selectedFile.pending = false;
    this.selectedFile.status = 'ok';
  }
  private onError() 
  {
    this.selectedFile.pending = false;
    this.selectedFile.status = 'fail';
    this.selectedFile.src = '';
  }
  processFile(imageInput: any) 
  {
    const file: File = imageInput.files[0];
    const reader = new FileReader();

    reader.addEventListener('load', (event: any) => 
    {
      this.selectedFile = new ImageSnippet(event.target.result, file);
      this.selectedFile.pending = true;
      this.imageService.uploadImage(
        this.selectedFile.file).subscribe((res) => 
        {
          this.onSuccess();},(err) => 
            {this.onError();
        }
        )}
     );

    reader.readAsDataURL(file);
    }
}

We added new properties to the ImageSnippet: Pending and Status. Pending can be false or true, depending if an image is currently being uploaded. Status is the result of the uploading process. It can be OK or FAILED.


OnSuccess and onError are called after the image upload and they set the status of an image.


Ok, now let’s take a look at the updated template file:

<label class="image-upload-container btn btn-bwm">
     <span>Select Image</span>
     <input #imageInput
         type="file"
         accept="image/*"(change)="processFile(imageInput)">
</label>

<div *ngIf="selectedFile" class="img-preview-container">
    <div class="img-preview{{selectedFile.status === 'fail' ? '-error' :     
    ''}}"[ngStyle]="{'background-image': 'url('+ selectedFile.src + ')'}">
    </div>
    <div *ngIf="selectedFile.pending" class="img-loading-overlay">
        <div class="img-spinning-circle">
        </div>
    </div>
    <div *ngIf="selectedFile.status === 'ok'" class="alert alert-success"> 
    Image Uploaded Succesfuly!
    </div>
    <div *ngIf="selectedFile.status === 'fail'" class="alert alert-
    danger"> Image Upload Failed!
    </div>
</div>


Resource: freecodecamp.org


The Tech Platform

0 comments
bottom of page