首页 > 数据库技术 > 详细

[AngularFire] Angular File Uploads to Firebase Storage with Angular control value accessor

时间:2017-10-22 10:15:00      阅读:296      评论:0      收藏:0      [点我收藏+]

The upload class will be used in the service layer. Notice it has a constructor for file attribute, which has a type of File. This will allows us to initialize new uploads with a JavaScript File object. You will see why this is important in the next step.

export class Upload {
  $key: string;
  file:File;
  name:string;
  url:string;
  progress:number;
  createdAt: Date = new Date();
  constructor(file:File) {
    this.file = file;
  }
}

 

Then build the upload service, which can inject to component:

import { Injectable } from ‘@angular/core‘;
import {Subject} from ‘rxjs/Subject‘;
import {MatSnackBar} from ‘@angular/material‘;

import * as firebase from ‘firebase‘;
import UploadTaskSnapshot = firebase.storage.UploadTaskSnapshot;
import {Upload} from ‘./upload‘;

@Injectable()
export class UploadService {

  uploading$ = new Subject<number>();
  completed$ = new Subject<Upload>();

  constructor(
    private snackBar: MatSnackBar
  ) {

  }

  uploadFile(upload: Upload, folder: string) {

    // Create a storage ref
    const storageRef = firebase.storage().ref();
    const uploadTask = storageRef.child(`${folder}/${upload.file.name}`).put(upload.file);
    // Upload file
    uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
      (snapshot: UploadTaskSnapshot) => {
        upload.progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        this.uploading$.next(upload.progress);
      },
      (err) => {
        this.snackBar.open(err.message, ‘OK‘, {
          duration: 3000,
        });
      },
      () => {
        upload.url = uploadTask.snapshot.downloadURL;
        upload.name = upload.file.name;
        this.completed$.next(upload);
        this.uploading$.next(null);
      });
  }

  deleteUpload(name: string, folder: string) {
    const storageRef = firebase.storage().ref();
    storageRef.child(`${folder}/${name}`).delete();
    this.completed$.next();
  }
}

 

Component:

import {ChangeDetectionStrategy, Component, forwardRef, Input} from ‘@angular/core‘;
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from ‘@angular/forms‘;

import {UploadService} from ‘../../services/upload.service‘;
import {Upload} from ‘../../services/upload‘;
import {Observable} from ‘rxjs/Observable‘;

export const TYPE_CONTROL_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  multi: true,
  useExisting: forwardRef(() => ImageUploaderComponent)
};

@Component({
  selector: ‘image-uploader‘,
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [TYPE_CONTROL_ACCESSOR],
  templateUrl: ‘./image-uploader.component.html‘,
  styleUrls: [‘./image-uploader.component.scss‘]
})
export class ImageUploaderComponent implements ControlValueAccessor {

  @Input() img;

  private onTouch: Function;
  private onModelChange: Function;
  private value: string;

  file: Upload;
  currentUpload: Upload;
  progress$: Observable<number>;

  constructor(private uploadService: UploadService) {
    this.progress$ = this.uploadService.uploading$;
    this.uploadService.completed$.subscribe((upload) => {

      if (upload) {
        this.setSelected(upload.url);
        this.currentUpload = upload;
      } else {
        this.setSelected(‘‘);
        this.currentUpload = null;
      }
    });
  }

  onChange($event) {
    const file = $event.target.files[0];
    this.file = new Upload(file);
    this.uploadService.uploadFile(this.file, ‘icons‘);
  }

  writeValue(value: any): void {
    this.value = value;
  }

  registerOnChange(fn: Function): void {
    this.onModelChange = fn;
  }

  registerOnTouched(fn: Function): void {
    this.onTouch = fn;
  }

  setSelected(value: string): void {
    this.value = value;
    this.onModelChange(value);
    this.onTouch();
  }

  clear() {
    if (this.file) {
      this.uploadService.deleteUpload(this.file.name, ‘icons‘);
      this.setSelected(‘‘);
    }
  }
}

 

Template:

    <div *ngIf="progress$ | async as p">
      <mat-progress-bar mode="determinate" [value]="p"></mat-progress-bar>
    </div>
    <mat-card-subtitle>
      Select / upload icon
    </mat-card-subtitle>

    <mat-card-content fxLayout="column">
      <div fxLayout="row" fxLayoutAlign="space-around">
        <div
          *ngIf="currentUpload"
          class="image-container"
          fxFlex="30%">
          <img [src]="currentUpload?.url || ‘‘" [alt]="currentUpload?.name || ‘‘">
        </div>
      </div>

 

[AngularFire] Angular File Uploads to Firebase Storage with Angular control value accessor

原文:http://www.cnblogs.com/Answer1215/p/7707593.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!