Merhabalar. Bu yazı içerisinde size bir Angular projesinden Rest API çağırımı sırasında nasıl dosya yüklenebileceğini anlatacağım. Bu yazı sırasında göreceğiniz kodlar https://github.com/ilkgunel/MemberFrontEndProject adresinden erişebileceğiniz MemberFrontEndProject içerisinde yer almaktadır.

MemberFrontEndProject projesinin API kısmı olan MemberRestAPIProject içerisinde yer alan 2 web servis kendilerine gelen CSV dosyası vasıtası ile sisteme çoklu üye kaydı yapabilmekte. Biz de MemberFrontEndProject üzerinden dosya yükleyerek çoklu admin üye ekleme servisini çağıracağız. MemberFrontEndProject hakkında bilgi verdiğim bir videoyu daha önce YouTube hesabıma yüklemiştim. İlgilenen arkadaşlar şu adresten o videoyu izleyebilirler : https://www.youtube.com/watch?v=Ta2UtJpXPSI

add-bulk-admin-member-dialog.component.html

<p>Choose Your File:</p>
<form [formGroup] = "addBulkAdminForm" (ngSubmit)="onSubmit()">
    <div class="form-group">
        <input type="file" formControlName="bulkAdminFile" class="form-control" [ngClass] = "{'is-invalid' : submitted && f.bulkAdminFile.errors }" (change) = "onFileChange($event)" />
        <div *ngIf="submitted && f.bulkAdminFile.errors" class="invalid-feedback">
            <div *ngIf="f.bulkAdminFile.errors.required">Flights File is required</div>
        </div>
    </div>
    <div class="form-group">
        <button [disabled]="loading" class="btn btn-primary">Upload</button>
        <img *ngIf="loading" class="pl-2" src="loadingGifAddress" />
    </div>
    <div *ngIf="error&&!fileUploadMessage" class="alert alert-danger">
      
    </div>
    <div *ngIf="fileUploadMessage" class="alert alert-primary">
        
    </div>
</form>

add-bulk-admin-member-dialog.component.html dosyamızda formGroup ile klasik bir Angular formu tanımlıyoruz. (ngSubmit) özelliğine onSubmit() metodunu atıyarak bu form submit edildiğinde .ts dosyası içerisindeki onSubmit metodu çağırılmasını söylüyoruz.

Form içerisinde file tipinde veri kabul edecek bir input element’i tanımlıyoruz. .ts dosyasında bu element’i tanıyabilmek için formControlName özelliğine bulkAdminFile değerini atıyoruz. (change) özelliğine yine TS dosyası içerisinde tanımlı olan onFileChange(event) metodunu atıyoruz. onFileChange bizim için dosya yükleme ve dosya değişim olaylarını takip edecek.

Input element’imizin altında ise eğer dosya seçilmeden form gönderilmeye kalkılırsa dosya seçiminin zorunlu olduğuna dair mesaj çıkaran bir yapımız mevcut.

Bunlarından yanında submit işlevini görecek Upload butonumuz, Upload yapıldığında belirecek loading gifimiz, eğer dosya yükleme işlemi hata alırsa bu hatayı bildirecek error div’imiz ve son olarak dosya işlemi sonunda dönen mesajı bildirecek bir div’imiz yer alıyor.

add-bulk-admin-member-dialog.component.spec.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MatDialogRef } from '@angular/material';
import { MemberService } from 'src/services/member.service';
import { HttpErrorResponse } from '@angular/common/http';

@Component({
  selector: 'add-bulk-admin-member-dialog',
  templateUrl: './add-bulk-admin-member-dialog.component.html',
  styleUrls: ['./add-bulk-admin-member-dialog.component.css']
})
export class AddBulkAdminMemberDialog implements OnInit {

  addBulkAdminForm : FormGroup;
  loading = false;
  submitted = false;
  error = '';
  fileUploadMessage = '';

  selectedFile : File;

  constructor(public dialogRef : MatDialogRef<AddBulkAdminMemberDialog>,
              private formBuilder : FormBuilder,
              private memberService : MemberService) { }

  ngOnInit() {
    this.addBulkAdminForm = this.formBuilder.group({
      bulkAdminFile : ['', Validators.required]
    })
  }

  get f() {
    return this.addBulkAdminForm.controls;
  }

  onFileChange(event) {
    if(event.target.files.length > 0) {
      const file = event.target.files[0];
      this.selectedFile = file;
    }
  }

  onSubmit() {
    this.submitted = true;
    if(this.addBulkAdminForm.invalid) {
      return;
    }

    this.loading = true;

    const formData = new FormData();
    formData.append("file", this.selectedFile);

    this.memberService.addBulkAdmin(formData)
    .subscribe(data => {
      this.fileUploadMessage = data.body.result;
      this.loading = false;
      this.delay(3000).then(any => {
        this.dialogRef.close();
      });
    },
    (error : HttpErrorResponse) => {
      this.error = error.error.errorCode + ' ' + error.error.result;
      this.loading = false;
    })
  }

  async delay(ms: number) {
    await new Promise(resolve => setTimeout(()=>resolve(), ms)).then(()=>console.log("fired"));
  }

}

.ts dosyamız olan add-bulk-admin-member-dialog.component.spec.ts dosyamız içerisinde öncelikle HTML dosyamızda formGroup özelliğine atanmış olan addBulkAdminForm değişkenimizi FormGroup tipinde olacak şekilde tanımlıyoruz. Diğer değişkenlerimiz olan loading, submitted, error ve fileUploadMessage değişkenlerimizi de başlangıç değerleri vererek oluşturuyoruz. Bir tane de File tipinde selectedFile değişkeni tanımlıyoruz. Bu değişkeni seçilen dosyanın API’ya gönderimi sırasında kullanacağız.

Constructor’ımız içerisinde dosya seçim ekranı bir dialog üzerinde açılacağından bir MatDialogRef nesnesi inject ediyoruz. addBulkAdminForm’u oluşturabilmek için bir FormBuilder ve servis metotlarımızın yer aldığı MemberService tipinden bir nesneyi de çağırım yapmak için inject ediyoruz.

ngOnInit() metodu içerisinde addBulkAdminForm’u oluşturuyoruz ve HTML dosyamızda tanımlı olan bulkAdminFile element’imizin Validators.required ile zorunlu bir alan olduğunu bildiriyoruz.

onFileChange(event) metodu ile her dosya seçiminde selectedFile değişkenimizi seçilen dosya ile değiştiriyoruz.

onSubmit() metodu içerisinde önce submit edilen form geçersiz mi diye bakıyor, geçersiz ise önünü kesiyoruz. Geçerli bir form ise bir FormData değişkeni oluşturup seçilen dosyayı file adı ile bu FormData değişkenine append ediyoruz. Akabinde memberService içerisindeki addBulkAdmin metoduna bu formData değişkenini parametre geçiyoruz. subscribe içerisinde işlemin başarılı ya da başarısız olması durumuna göre case’lerimiz mevcut.

addBulkAdmin(formData) Metodu

addBulkAdmin(formData) {
    this.response = this.http.post<OperationResult>(environment.bulkAdminAddUrl, formData, {observe : 'response'} );
    return this.response;
}

formData’yı parametre olarak kabul eden addBulkAdmin metodumuz http://localhost:8080/MemberRestAPIProject/bulk/add/admin değerine sahip olan bulkAdminAddUrl adresine bu formData’yı gönderiyor. Az önce gördüğümüz gibi bu formData içerisinde seçilen dosyamız mevcut idi.

DEMO

Şimdi bu yazdıklarımızın bir demosunu yapalım.

MemberFrontEndProject’in ana sayfasında iken Add Bulk Admin Member butonuna tıklıyorum.

Bir dialog ekranı açılacak. Bu ekranda Choose File butonu ile bir CSV dosyası seçiyorum. Benim seçtiğim CSV dosyasının adı members.csv şeklinde.

CSV dosyasının içeriği de şöyle :

Sheldon,Cooper,sheldon@ilkaygunel.com,TEST1234,EN
Leonard,Hofstadter,leonard@ilkaygunel.com,TEST1234,EN
Howard,Wolowitz,howard@ilkaygunel.com,TEST1234,EN
Rajesh,Koothrappali,rajesh@ilkaygunel.com,TEST1234,EN

CSV dosyası seçimi sonrası Upload butonuna tıklıyorum ve bana dosya ile üye ekleme işleminin başarılı olduğuna dair bir mesajın döndüğünü görüyorum.

Tekrar ana sayfadan kontrol yaptığımda CSV dosyasının içindeki 4 kişinin sisteme başarılı şekilde kayıt olduğunu görebiliyorum.

Bu yazıda anlatacaklarım bu kadar arkadaşlar. Sorularınız ya da yazı içerisinde geliştirilmesi gerektiğini düşündüğünüz yerler için yorum yazmayı unutmayın :)

Başka yazıda görüşenece kadar sağlıcakla kalın.

Selam ve Sevgilerimle