التثبيت: npm i angular/fire يمكننا حفظ أي ملف نحتاجه على الـ Firebase Storage من خلال الأكواد التالية:
https://stackoverflow.com/questions/68939014/angularfiremodule-and-angularfiredatabasemodule-not-being-found-in-angular-fire
بداية لا بد من استدعاء المكتبات التالية في الـ app.module.ts
import { AngularFireModule } from '@angular/fire/compat' ;
import { AngularFireStorageModule } from '@angular/fire/compat/storage' ;
imports : [
AngularFireStorageModule ,
AngularFireModule .initializeApp ({
apiKey : "" ,
authDomain : "" ,
databaseURL : "" ,
projectId : "" ,
storageBucket : "" ,
messagingSenderId : "" ,
appId : ""
}),
AppRoutingModule ,
BrowserModule ,
FormsModule ,
HttpClientModule ,
MaterialModule ,
ReactiveFormsModule ,
provideFirebaseApp (() => initializeApp (environment .firebase )),
provideAuth (() => getAuth ()),
provideDatabase (() => getDatabase ()),
provideFirestore (() => getFirestore ()),
BrowserAnimationsModule ,
LayoutModule ,
MatToolbarModule ,
MatButtonModule ,
MatSidenavModule ,
MatIconModule ,
MatListModule ,
TranslateModule .forRoot ({
defaultLanguage : 'ar' ,
loader : {
provide : TranslateLoader ,
useFactory : HttpLoaderFactory ,
deps : [HttpClient ]
}
})
],
في الملف التابع للمكون يكون الكود بهذا الشكل:
import { Component , ElementRef , Inject , Injectable , ViewChild } from '@angular/core' ;
import { FormBuilder , Validators } from '@angular/forms' ;
import { MatSnackBar } from '@angular/material/snack-bar' ;
import { onValue } from 'firebase/database' ;
import { User } from 'src/app/models/user' ;
import { FirebaseService } from 'src/app/services/firebase.service' ;
import { LocalStorageService } from 'src/app/services/local-storage.service' ;
import { AngularFireStorage } from '@angular/fire/compat/storage' ;
import { concatWith , finalize , Observable } from 'rxjs' ;
import { TaskState } from 'firebase/firestore' ;
import { UploadTask , UploadTaskSnapshot } from '@angular/fire/compat/storage/interfaces' ;
@Component ({
selector : 'app-personal-profile' ,
templateUrl : './personal-profile.component.html' ,
styleUrls : ['./personal-profile.component.scss' ]
})
export class PersonalProfileComponent {
@ViewChild ('hiddenPictube' ) hiddenPictube : ElementRef <HTMLInputElement >;
path : any ;
onlineImage : any ;
imageBaseRef : any ;
imageRef : any ;
//Storage Variables
uploadPercent : Observable <number >;
downloadURL : Observable <string >;
profileUrl : any ;
personalInfoForm = this ._formBuilder .group ({
firstName : ['' , Validators .required ],
lastName : ['' , Validators .required ],
titleJob : ['' , Validators .required ],
enTitleJob : ['' , Validators .required ],
employeeId : ['' , Validators .required ],
email : ['' , Validators .compose ([Validators .required , Validators .email ])],
mobileNo : ['' , Validators .required ],
});
constructor (private storage : AngularFireStorage ) {
}
ngOnInit (): void {
}
updateInfo () {
if (this .personalInfoForm .status === "VALID" ) {
this .user .picture = (this .hiddenPictube .nativeElement .value .trim () !== "" ) ? this .hiddenPictube .nativeElement .value : this .user .picture ;
this .editPersonalInfo = !this .editPersonalInfo ;
this .user .createdAt = this .user .createdAt ;
this .user .modifiedAt = this .user .modifiedAt ;
this .user .createdBy = this .user .email ;
this .user .modifiedBy = this .user .email ;
this .firebaseService .updateUser (this .user .id , this .user );
this .hiddenPictube .nativeElement .value = "" ;
} else {
this .openSnackBar ("يرجى التحقق من أنّ جميع المدخلات صحيحة!" , "إغلاق" );
}
}
async upload (event : any ) {
const file = event .target .files [0 ];
const filePath = "profiles/profile_" + this .user .id + "." + file .name .split ('.' )[1 ];
const fileRef = this .storage .ref (filePath );
const task = this .storage .upload (filePath , file );
// observe percentage changes
this .uploadPercent = task .percentageChanges ();
// get notified when the download URL is available
task .snapshotChanges ().pipe (
finalize (() => {
this .downloadURL = fileRef .getDownloadURL ();
})).subscribe ();
}
uploadChange () {
this .user .picture = this .hiddenPictube .nativeElement .value ;
this .firebaseService .updateUser (this .user .id , this .user );
}
}
أما كود الـ HTML للمكون فهو كالتالي:
< div class ="padding" >
< div class ="row container w-100 d-flex justify-content-center" >
< div class ="col-xl-12 col-md-12" >
< div class ="card user-card-full" >
< div class ="row m-l-0 m-r-0" >
< div class ="col-sm-4 bg-c-lite-green user-profile" >
< div class ="card-block text-center text-white" >
< div class ="m-b-25" >
< img #userPicture [src] ="user.picture" style =" width: 150px;height: 150px;" class ="mg-thumbnail mb-4 mt-2 rounded-circle" [alt] ="user.firstName" >
< input [style] ="(editPersonalInfo == false)? 'display:none;':'display:block;'" type ="file" (change) ="upload($event);" accept ="*.png.jpg" >
<!-- <i (click)="uploadImage()" [style]="(editPersonalInfo == false)? 'display:none;':'display:block;'"
class="mdi mdi-image-edit feather icon-edit m-t-10 f-25" [matTooltip]="'تغيير الصورة'"></i> -->
</ div >
< input ngModel #hiddenPictube (change) ="uploadChange()" type ="hidden" [value] ="downloadURL | async" >
< h6 class ="f-w-600" > {{ user.firstName + ' '+ user.lastName }}</ h6 >
< p > {{ user.titleJob }}</ p >
<!-- <a (click)="uploadChange()">fgfdgdfg</a> -->
< i (click) ="updateInfo();"
[class] ="(editPersonalInfo == false)? 'mdi mdi-square-edit-outline feather icon-edit m-t-10 f-25' : 'mdi mdi-content-save feather icon-edit m-t-10 f-25'"
[matTooltip] ="(editPersonalInfo == false)? 'تحرير المعلومات':'حفظ التغييرات'" ></ i >
<!-- {{ editPersonalInfo }} -->
</ div >
</ div >
< div class ="col-sm-8" >
< form [formGroup] ="personalInfoForm" >
< div class ="card-block" >
< h6 class ="m-b-20 p-b-5 b-b-default f-w-600" > المعلومات الشخصية</ h6 >
< div class ="row" >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600"
[style] ="(editPersonalInfo == false)? 'display: block;': 'display: none;'" >
الاسم
الأول</ p >
< h6 [style] ="(editPersonalInfo == false)? 'display: inline;': 'display: none;'"
class ="text-muted f-w-400" > {{user.firstName}}</ h6 >
< mat-form-field [style] ="(editPersonalInfo == false)? 'display: none;': 'display: inline;'" >
< mat-label > الاسم الأول</ mat-label >
< input matInput formControlName ="firstName" [(ngModel)] ="user.firstName" #first_name
maxlength ="50" placeholder ="مثلاً: محمد" required >
< mat-error align ="start" *ngIf ="personalInfoForm.controls['firstName'].hasError('required')" >
هذا الحقل إلزامي
</ mat-error >
<!-- <mat-hint align="start"><strong>اسمك هذا سيكون معتمداً برمجياً</strong>
</mat-hint> -->
< mat-hint align ="end" > {{first_name.value.length}} / 50</ mat-hint >
</ mat-form-field >
</ div >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600"
[style] ="(editPersonalInfo == false)? 'display: block;': 'display: none;'" >
الاسم
الأخير</ p >
< h6 [style] ="(editPersonalInfo == false)? 'display: inline;': 'display: none;'"
class ="text-muted f-w-400" > {{user.lastName}}</ h6 >
< mat-form-field [style] ="(editPersonalInfo == false)? 'display: none;': 'display: inline;'" >
< mat-label > الاسم الأخير</ mat-label >
< input matInput formControlName ="lastName" [(ngModel)] ="user.lastName" #last_name maxlength ="50"
placeholder ="مثلاً: السالم" required >
<!-- <mat-hint align="start"><strong>اسمك هذا سيكون معتمداً برمجياً</strong>
</mat-hint> -->
< mat-error align ="start" *ngIf ="personalInfoForm.controls['lastName'].hasError('required')" >
هذا الحقل إلزامي
</ mat-error >
< mat-hint align ="end" > {{last_name.value.length}} / 50</ mat-hint >
</ mat-form-field >
</ div >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600"
[style] ="(editPersonalInfo == false)? 'display: block;': 'display: none;'" >
المسمى الوظيفي</ p >
< h6 [style] ="(editPersonalInfo == false)? 'display: inline;': 'display: none;'"
class ="text-muted f-w-400" > {{user.titleJob}}</ h6 >
< mat-form-field [style] ="(editPersonalInfo == false)? 'display: none;': 'display: inline;'" >
< mat-label > المسمى الوظيفي</ mat-label >
< input formControlName ="titleJob" [(ngModel)] ="user.titleJob" matInput #title_job maxlength ="50"
placeholder ="مثلاً: مهندس برمجيات" required >
<!-- <mat-hint align="start"><strong>يرجى كتابة مسماك الوظيفي</strong>
</mat-hint> -->
< mat-error align ="start" *ngIf ="personalInfoForm.controls['titleJob'].hasError('required')" >
هذا الحقل إلزامي
</ mat-error >
< mat-hint align ="end" > {{title_job.value.length}} / 50</ mat-hint >
</ mat-form-field >
</ div >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600"
[style] ="(editPersonalInfo == false)? 'display: block;': 'display: none;'" >
المسمى الوظيفي بالإنجليزي</ p >
< h6 [style] ="(editPersonalInfo == false)? 'display: inline;': 'display: none;'"
class ="text-muted f-w-400" > {{user.enTitleJob}}</ h6 >
< mat-form-field [style] ="(editPersonalInfo == false)? 'display: none;': 'display: inline;'" >
< mat-label > المسمى الوظيفي بالإنجليزي</ mat-label >
< input formControlName ="enTitleJob" [(ngModel)] ="user.enTitleJob" matInput #en_title_job
maxlength ="50" placeholder ="مثلاً: Software Engineer" required >
< mat-error align ="start" *ngIf ="personalInfoForm.controls['enTitleJob'].hasError('required')" >
هذا الحقل إلزامي
</ mat-error >
<!-- <mat-hint align="start"><strong>يرجى كتابة مسماك الوظيفي بالإنجليزي</strong>
</mat-hint> -->
< mat-hint align ="end" > {{en_title_job.value.length}} / 50</ mat-hint >
</ mat-form-field >
</ div >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600"
[style] ="(editPersonalInfo == false)? 'display: block;': 'display: none;'" >
الرقم
الوظيفي</ p >
< h6 [style] ="(editPersonalInfo == false)? 'display: inline;': 'display: none;'"
class ="text-muted f-w-400" > {{user.employeeId}}</ h6 >
< mat-form-field [style] ="(editPersonalInfo == false)? 'display: none;': 'display: inline;'" >
< mat-label > الرقم الوظيفي</ mat-label >
< input formControlName ="employeeId" [(ngModel)] ="user.employeeId" matInput #employee_id
type ="text"
onKeyPress ="if(this.value.length==10) return false; return event .charCode >= 48 && event .charCode < = 57"
placeholder ="مثلاً: 1115" required >
< mat-error align ="start" *ngIf ="personalInfoForm.controls['employeeId'].hasError('required')" >
هذا الحقل إلزامي
</ mat-error >
<!-- <mat-hint align="start"><strong>يرجى إدخال الرقم الوظيفي بدقة</strong>
</mat-hint> -->
< mat-hint align ="end" > {{employee_id.value.length}} / 10</ mat-hint >
</ mat-form-field >
</ div >
</ div >
< h6 class ="m-b-20 m-t-40 p-b-5 b-b-default f-w-600" > معلومات الاتصال</ h6 >
< div class ="row" >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600"
[style] ="(editPersonalInfo == false)? 'display: block;': 'display: none;'" >
البريد الإلكتروني</ p >
< h6 [style] ="(editPersonalInfo == false)? 'display: inline;': 'display: none;'"
class ="text-muted f-w-400" > {{user.email}}</ h6 >
< mat-form-field [style] ="(editPersonalInfo == false)? 'display: none;': 'display: inline;'" >
< mat-label > البريد الإلكتروني</ mat-label >
< input formControlName ="email" matInput [(ngModel)] ="user.email" #email type ="email"
maxlength ="50" placeholder ="مثلاً: abc@abc.com" required >
< mat-error align ="start" *ngIf ="personalInfoForm.controls['email'].hasError('required')" >
هذا الحقل إلزامي
</ mat-error >
< mat-error
*ngIf ="personalInfoForm.controls['email'].hasError('email') && !personalInfoForm.controls['email'].hasError('required')" >
البريد الإلكتروني المدخل غير صحيح!
</ mat-error >
<!-- <mat-hint align="start"><strong>يرجى إدخال بريد صحيح</strong> </mat-hint> -->
< mat-hint align ="end" > {{email.value.length}} / 50</ mat-hint >
</ mat-form-field >
</ div >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600"
[style] ="(editPersonalInfo == false)? 'display: block;': 'display: none;'" >
رقم
الجوال</ p >
< h6 [style] ="(editPersonalInfo == false)? 'display: inline;': 'display: none;'"
class ="text-muted f-w-400" > {{user.mobileNo}}</ h6 >
< mat-form-field [style] ="(editPersonalInfo == false)? 'display: none;': 'display: inline;'" >
< mat-label > رقم الجوال</ mat-label >
< input formControlName ="mobileNo" matInput [(ngModel)] ="user.mobileNo" #mobile_no type ="text"
onKeyPress ="if(this.value.length==10) return false; return event .charCode >= 48 && event .charCode < = 57"
placeholder ="مثلاً: 0508532127" required >
< mat-error align ="start" *ngIf ="personalInfoForm.controls['mobileNo'].hasError('required')" >
هذا الحقل إلزامي
</ mat-error >
<!-- <mat-hint align="start"><strong>يرجى كتابة الأرقام فقط</strong> </mat-hint> -->
< mat-hint align ="end" > {{mobile_no.value.length}} / 10</ mat-hint >
</ mat-form-field >
</ div >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600" > إنشاء الحساب</ p >
< h6 class ="text-muted f-w-400" > {{user.createdAt | date:'dd-MM-yyyy - hh:mm a'}}</ h6 >
</ div >
< div class ="col-sm-6 mt-2" >
< p class ="m-b-10 f-w-600" > آخر نشاط</ p >
< h6 class ="text-muted f-w-400" > {{user.lastActive | date: 'dd-MM-yyyy - hh:mm a'}}</ h6 >
</ div >
</ div >
</ div >
</ form >
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
الرجع:
https://github.com/angular/angularfire/blob/master/docs/storage/storage.md
https://github.com/angular/angularfire/blob/master/docs/version-7-upgrade.md
المشاكل: مشكلة: node_modules/@angular/fire/compat/firestore/interfaces.d.ts:29:33
29 export interface DocumentChange<T> extends firebase.firestore.DocumentChange {
الحل: https://stackoverflow.com/questions/73281199/error-when-importing-angularfiredatabasemodule
https://github.com/angular/angularfire/issues/3290#issuecomment-1323837275
------------------------------------------------------------------------------------------
الطريقة الأفضل كالتالي:
VIDEO
التثبيتات الهامة:https://www.npmjs.com/package/angularfire2
------------------------------------------------------------------------------------------
الطريقة الأفضل كود الـ ts
import { Injectable } from '@angular/core' ;
import { Observable , finalize } from 'rxjs' ;
import { AngularFireStorage , AngularFireStorageReference , AngularFireUploadTask } from '@angular/fire/compat/storage' ;
@Injectable ({
providedIn : 'root'
})
export class UpluadFilesService {
uploadProgress : Observable <any >;
ref : AngularFireStorageReference ;
task : AngularFireUploadTask ;
downloadURL : Observable <string >;
constructor (
private afStorage : AngularFireStorage ,
) { }
async uploadSlow (event : any ) {
let role = '' !== '' && '' !== '' ;
if (role ) {
const id = "cv_" + "Abdullah" + "_" + 'Alsalem' ;//Math.random().toString(36).substring(2)
const file = event .target .files [0 ];
const filePath = "cv/" + id + "." + file .name .split ('.' )[1 ];
this .ref = this .afStorage .ref (filePath );
this .task = this .ref .put (file );
this .uploadProgress = this .task .percentageChanges ();
this .downloadURL = new Observable ;
this .downloadURL = await this .ref .getDownloadURL ();
// this.employmentApplication.cv = this.cv.nativeElement.value;
} else {
let message = 'hi' ;
alert (message );
}
}
uploadFast (event : any , theObject : any ,
uploadProgress : Observable <any >, downloadURL : Observable <string >
): Observable <string > {
const file = event .target .files [0 ];
const filePath = "cv/cv_" + (Math .floor (Math .random () * (150 - 1 ) + 1 )) + "." + file .name .split ('.' )[1 ];
const fileRef = this .afStorage .ref (filePath );
const task = this .afStorage .upload (filePath , file );
// observe percentage changes
uploadProgress = task .percentageChanges ();
// get notified when the download URL is available
task .snapshotChanges ().pipe (
finalize (() => {
downloadURL = fileRef .getDownloadURL ();
// theObject.cv = refHtml.nativeElement.value;
})
)
.subscribe ();
return downloadURL ;
}
}
كود الـ HTML
< div class ="col-12 col-md-6 mt-3" >
< div class ="mt-4 row" >
< mat-label class ="label col-4" > {{'LABELS.ATTACH_CV' | translate}} : </ mat-label >
<!-- <button (click)="fileUpload.click()"></button> -->
< input id ="input-file-id" (change) ="uploadFile($event)" class ="col-8"
accept =".pdf, .doc, .docx, |file/*" type ="file" />
< div class ="col-12 mt-2 progress" *ngIf ="!(downloadURL | async)" >
< div class ="progress-bar progress-bar-striped bg-success" role ="progressbar"
[style.width] ="(uploadProgress | async) + '%'"
[attr.aria-valuenow] ="(uploadProgress | async)" aria-valuemin ="0"
aria-valuemax ="100" >
</ div >
</ div >
< b class ="mt-2" *ngIf ="!(downloadURL | async)" > {{'WARNING.DELAYED_UPLOAD' | translate}}</ b >
< span class ="col-12 mt-2" *ngIf ="!(downloadURL | async)" > {{('WARNING.UPLOAD_FILE' |
translate) + ' {' + (uploadProgress |
async) + '% }' }}</ span >
< input ngModel #cv type ="hidden" [value] ="downloadURL | async" >
< div *ngIf ="downloadURL | async; let downloadSrc" class ="col-12 mt-2 alert alert-info"
role ="alert" >
{{'SUCCESS.FILE_UPLOADED' | translate}}: < a [href] ="downloadSrc"
target ="_blank" > {{'BUTTONS.VIEW_FILE' | translate}}</ a >< br >
<!-- <input (change)="updateCvValue(downloadSrc)"
type="text" [value]="downloadSrc"> -->
</ div >
< mat-error align ="start" *ngIf ="secondFormGroup.controls['cv_file'].hasError('required')" >
{{'ERRORS.REQUIRED' | translate}}
</ mat-error >
</ div >
</ div >
والأهم وبدونه لن يعمل الكود مطلقاً إعدادات الـ app.module.ts
آخر ما توصلتُ له من إنتاجية:
//-----------------------------------upload files--------------------------
async uploadForDragDrop (files : any ) {
const generateName = this .maintenanceTicket .subject + " (" + this .maintenanceTicket .request_type + ")" ;//Math.random().toString(36).substring(2)
const file = files [0 ];
const filePath = "maintenancesTickets/" + generateName + "." + file .name .split ('.' )[1 ];
const fileRef = this .storage .ref (filePath );
const task = this .storage .upload (filePath , file );
const fileSizeInMB = file .size / (1024 * 1024 ); // Convert file size to MB
if (fileSizeInMB <= 10 ) {
// File size is less than or equal to 10 MB, accept the file
// Perform further processing or upload the file
// observe percentage changes
this .uploadPercent = task .percentageChanges ();
// get notified when the download URL is available
task .snapshotChanges ().pipe (
finalize (() => {
this .downloadURL = fileRef .getDownloadURL ();
this .waitingDownloadFile = true ;
setTimeout (() => {
let attachment = new MaintenancesAttachment ();
attachment .maintenance = this .maintenanceTicket ;
attachment .name = generateName ;
attachment .type = file .type ;
this .extension = file .name .split ('.' )[1 ].toLocaleUpperCase ();
attachment .extension = file .name .split ('.' )[1 ].toLocaleUpperCase ();
attachment .file_size = fileSizeInMB ;
attachment .url = this .hiddenFile .nativeElement .value .trim ();
attachment .star = false ;
this .maintenancesAttachmentsService .postItem (attachment , true , this .uploadFile .nativeElement .value , '' );
}, 5000 ); // Delay of 2000 milliseconds (2 seconds)
this .waitingDownloadFile = false ;
})).subscribe (a => {
// this.maintenanceTicket.photo = (this.hiddenFile.nativeElement.value.trim() !== "") ? this.hiddenPictube.nativeElement.value : this.employee.photo;
});
} else {
this .snackBarService .openSnackBar (this .size10LessThan .nativeElement .value , '' );
}
}
async uploadFiles (event : any ) {
const generateName = this .maintenanceTicket .subject + " (" + this .maintenanceTicket .request_type + ")" ;//Math.random().toString(36).substring(2)
const file = event .target .files [0 ];
const filePath = "maintenancesTickets/" + generateName + "." + file .name .split ('.' )[1 ];
const fileRef = this .storage .ref (filePath );
const task = this .storage .upload (filePath , file );
const fileSizeInMB = file .size / (1024 * 1024 ); // Convert file size to MB
if (fileSizeInMB <= 10 ) {
// File size is less than or equal to 10 MB, accept the file
// Perform further processing or upload the file
// observe percentage changes
this .uploadPercent = task .percentageChanges ();
// get notified when the download URL is available
task .snapshotChanges ().pipe (
finalize (() => {
this .downloadURL = fileRef .getDownloadURL ();
this .waitingDownloadFile = true ;
setTimeout (() => {
let attachment = new MaintenancesAttachment ();
attachment .maintenance = this .maintenanceTicket ;
attachment .name = generateName ;
attachment .type = file .type ;
this .extension = file .name .split ('.' )[1 ].toLocaleUpperCase ();
attachment .extension = file .name .split ('.' )[1 ].toLocaleUpperCase ();
attachment .file_size = fileSizeInMB ;
attachment .url = this .hiddenFile .nativeElement .value .trim ();
attachment .star = false ;
this .maintenancesAttachmentsService .postItem (attachment , true , this .uploadFile .nativeElement .value , '' );
this .waitingDownloadFile = false ;
}, 5000 ); // Delay of 2000 milliseconds (2 seconds)
})).subscribe (a => {
// this.maintenanceTicket.photo = (this.hiddenFile.nativeElement.value.trim() !== "") ? this.hiddenPictube.nativeElement.value : this.employee.photo;
});
} else {
this .snackBarService .openSnackBar (this .size10LessThan .nativeElement .value , '' );
}
}
للتحقق من أبعاد الصور:
HTML
< input ngModel #hiddenFile type ="hidden" [value] ="downloadURL | async" >
< div class ="col-12 col-md-12 mt-3" >
< mat-label class ="mt-2" >< strong > {{'LABELS.IMAGE' | translate}}</ strong ></ mat-label >
< div (click) ="fileInput.click()" (drop) ="onDrop($event);" (dragover) ="onDragOver($event);"
class ="p-3 cursor-pointer mt-3 w-100 bg-for-attachments alyahya-text-primary border-for-attachments" >
< div class ="absolute" >
< div class ="d-flex justify-content-center" >
< span class ="block text-gray-400 font-normal" >
< i class ="mdi mdi-folder-open f-25 text-blue-700" ></ i > {{'BUTTONS.DRAG_AND_DROP' |
translate}} < br >
< mat-progress-bar class ="mt-3"
[matTooltip] ="'LOADING.PLEASE_WAIT_5_SECONDS' | translate"
*ngIf ="waitingDownloadFile" mode ="buffer" ></ mat-progress-bar >
< span *ngIf ="extension === 'PDF'" >< a
[href] ="downloadURL | async" > {{'BUTTONS.VIEW_FILE'
| translate}}</ a ></ span >
< br >
< img *ngIf ="extension === 'PNG' || extension === 'JPG' || extension === 'JPEG'"
style =" height: 288px; width: auto;" [src] ="downloadURL | async" alt ="" >
</ span >
</ div >
</ div >
<!-- opacity-0 -->
< input #fileInput (change) ="onFileSelected($event);uploadImage($event);" accept =".png, .jpg"
style =" display: none !important;" type ="file" class ="h-full w-full w-100" class ="d-block"
name ="" >
</ div >
TS
_validateDimensions : boolean = false ;
validateDimensions (width : number , height : number ) {
const minWidth = 1920 ; // Set your minimum width requirement
const minHeight = 345 ; // Set your minimum height requirement
if (width !== minWidth || height !== minHeight ) {
this ._validateDimensions = false ;
} else {
// Image dimensions are valid, proceed with upload logic (if applicable)
this ._validateDimensions = true ;
}
}
onFileSelected (event : any ) {
const file = event .target .files [0 ];
const reader = new FileReader ();
reader .onload = (e : any ) => {
const img = new Image ();
img .onload = () => {
this .validateDimensions (img .width , img .height ); // Call validation function
};
img .src = e .target .result ;
};
reader .readAsDataURL (file );
}
async uploadImage (event : any ) {
setTimeout (()=> {
if (this ._validateDimensions ){
this .extension = event .target .files [0 ].name .split ('.' )[1 ].toLocaleUpperCase ();
const generateName = event .target .files [0 ].name ;//Math.random().toString(36).substring(2)
const file = event .target .files [0 ];
if (this .extension === 'PNG' || this .extension === 'JPG' ) {
const filePath = "main-carousel/" + generateName ;
const fileRef = this .storage .ref (filePath );
const task = this .storage .upload (filePath , file );
const fileSizeInMB = file .size / (1024 * 1024 ); // Convert file size to MB
if (fileSizeInMB <= 10 ) {
this .uploadPercent = task .percentageChanges ();
task .snapshotChanges ().pipe (
finalize (() => {
this .downloadURL = fileRef .getDownloadURL ();
this .waitingDownloadFile = true ;
setTimeout (() => {
this .item .image = this .hiddenFile .nativeElement .value .trim ();
this .waitingDownloadFile = false ;
}, 5000 ); // Delay of 2000 milliseconds (2 seconds)
})).subscribe (a => {
});
} else {
this .snackBarService .openSnackBar (this .translateService .instant ('WARNING.SIZE_10_LESS_THAN' ), '' );
}
}
else {
this .snackBarService .openSnackBar (this .translateService .instant ('ERRORS.REJECT_EXTENSION' ), '' );
}
}else {
this .snackBarService .openSnackBar ('يجب أن تكون أبعاد الصورة 1920×345' ,'' )
}
}, 1000 );
}
تعليقات
إرسال تعليق