如何自定义输入类型文件图像的验证

时间:2019-01-09 00:45:41

标签: html angular

你好,我想验证输入文件html类型的图像,只接受'png', 'jpg', 'jpeg', 'gif'且不大于2mb,直到我确定只有输入它不会占用我this.firstFormGroup.controls.image .status时,其他任何文件都被激活为有效状态。

 handleFileInput(event) {

  const file = event.target.files[0];
  const typeFile = file.type.split('/');
  const filemb: number = file.size / 1000000;
  if (filemb <= 2 && (typeFile[1] === 'png' || typeFile[1] === 'jpg' || typeFile[1] === 'jpeg' || typeFile[1] === 'gif') ) {
        const filePath = `${this.rutaImg}/${file.name}`;
        const fileRef = this.storage.ref(filePath);
        const task = this.storage.upload(filePath, file);
        this.uploadPercent = task.percentageChanges();
        task.snapshotChanges().pipe(
            finalize(() => {
              this.downloadURL = fileRef.getDownloadURL();
              this.downloadURL.subscribe( url => {
                if ( url ) {
                  this.urlImg = url;
                  console.log(this.urlImg);
                  this.validateImage = true;
                  console.log(this.validateImage );
                  return {
                    isError: this.validateImage
                };
                }
             });
            })
         )
        .subscribe();

  } else {
    this.validateImage = false;
  }
}

html代码

    <div>
        <input formControlName="image"  (change)="handleFileInput($event)" type="file"  id="file" class="inputfile" accept="image/*"  required/>
        <label for="file"><mdb-icon icon="camera"></mdb-icon> Insertar Imagen &nbsp;
          <progress  style="margin-top: -10px; " *ngIf="uploadPercent" max="100" [value]="(uploadPercent | async)"></progress>
       </label>
 </div>

FormGroup

this.firstFormGroup = this.fb.group({
      ruc: ['', rucValidator],
      razon_social: ['', nameValidator],
      nameBussines: ['', nameValidator],
      phone: ['', phoneValidator],
      describe: ['', describeValidator],
      plan: ['', Validators.required],
      category: ['', Validators.required],
      image: ['', this.validateImage]
    });

3 个答案:

答案 0 :(得分:0)

您必须创建一个自定义FormControl,我将向您展示如何创建它(online example),也可以使用npm模块(FileInputAccessor


创建FormControl并上传有效文件的步骤

  1. 实现ControlValueAccessor
  2. 添加了自定义验证规则
    • 注册自定义验证规则
  3. 收听以您的反应形式更改事件
    • 将有效文件上传到您的存储空间

1。实施ControlValueAccessor

image-formcontrol.component

import { Component, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { ImageFormcontrol } from './image-formcontrol';
@Component({
  selector: 'app-image-formcontrol',
  templateUrl: './image-formcontrol.component.html',
  styleUrls: ['./image-formcontrol.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ImageFormcontrolComponent),
      multi: true
    }
  ]
})
export class ImageFormcontrolComponent implements OnInit, ControlValueAccessor {

  _registerOnChangeFn;
  _registerOnTouchedFn;

  constructor() { }

  ngOnInit() {
  }

  handleFileInput(event: Event) {

    const file = (event.target as HTMLInputElement).files[0];

    this.writeValue({
      file
    });
  }

  writeValue(value: ImageFormcontrol.Value) {
    if (this._registerOnTouchedFn) {
      this._registerOnTouchedFn();
    }

    if (this._registerOnChangeFn) {
      // update value and validity
      this._registerOnChangeFn(value);
    }
  }

  registerOnChange(fn) {
    this._registerOnChangeFn = fn;
  }

  registerOnTouched(fn) {
    this._registerOnTouchedFn = fn;
  }

}
<input (change)="handleFileInput($event)"  type="file"  id="file" class="inputfile" accept="image/*" />


2。添加了自定义验证规则

image-formcontrol-validator

  export function allowedTypes(pattern: string[]): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } | null => {
      const value = control.value as ImageFormcontrol.Value;

      const valid = null;
      const isUndefined = !value || !value.file;
      if (isUndefined) {
        return valid;
      }

      const allowed = new RegExp(`(${pattern.join('|')})`, 'ig').test(value.file.type);
      if (allowed) {
        return valid;
      } else {
        const invalid = { 'allowedTypes': { value: control.value } };
        return invalid;
      }
    };
  }

-

2-1。注册自定义验证规则

app.component(您可以将其更改为组件,仅用于演示目的)

export class AppComponent {

  firstFormGroup: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    const imageFormControl = new FormControl('', ImageFormcontrolValidator.allowedTypes(['jpeg']));

    this.firstFormGroup = this.fb.group({
      image: imageFormControl
    });
  }
}


3。以您的反应形式收听变化事件

  • 将有效文件上传到您的存储空间

export class AppComponent {

  firstFormGroup: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    const imageFormControl = new FormControl('', ImageFormcontrolValidator.allowedTypes(['jpeg']));

    this.firstFormGroup = this.fb.group({
      image: imageFormControl
    });

    imageFormControl.statusChanges.subscribe((status) => {
      switch (status) {
        case 'VALID':
          // Upload the valid file to your storage
          const value = imageFormControl.value as ImageFormcontrol.Value;
          this.upload(value.file);
          break;
      }
    });
  }

  private upload(file: File) {
    console.log('upload', file);

    /* your custom logic

    const filePath = `${this.rutaImg}/${file.name}`;
        const fileRef = this.storage.ref(filePath);
        const task = this.storage.upload(filePath, file);
        this.uploadPercent = task.percentageChanges();
        task.snapshotChanges().pipe(
            finalize(() => {
              this.downloadURL = fileRef.getDownloadURL();
              this.downloadURL.subscribe( url => {
                if ( url ) {
                  this.urlImg = url;
                  console.log(this.urlImg);
                  this.validateImage = true;
                  console.log(this.validateImage );
                  return {
                    isError: this.validateImage
                };
                }
             });
            })
         )
        .subscribe();

      */
  }
}

答案 1 :(得分:0)

我有一个可以帮助您或帮助任何人的飞弹。不是完美的,但是经过阅读和研究很多。我这样做仅是为了验证文件扩展名。

https://angular-fileupload-custom-validator-reactive-form.stackblitz.io

我在这里恢复:

  1. 为您的FormGroup或Form Builder创建自定义验证器。

  2. 将其添加到您的组件并定义允许的扩展数组 文件。

  3. 将无效或有效状态返回到您的输入表单。

答案 2 :(得分:0)

针对文件输入类型的所需文件的自定义验证

requiredFileType.ts

import { AbstractControl, FormControl } from "@angular/forms";
export function requiredFileType(type: string[]) {
  return function(control: FormControl) {
    // return (control: AbstractControl): { [key: string]: any } | null => {
    const file = control.value;
    const valid = null;
    if (file) {
      // console.log(file);
      var path = file.replace(/^.*[\\\/]/, "");
      //   var el_down = path
      //     .split("\\")
      //     .pop()
      //     .split("/")
      //     .pop();

      const extension = path.split(".")[1].toUpperCase();
      console.log(extension + "extension" + type.length);
      var existValue: boolean = false;
      for (var i = 0; i < type.length; i++) {
        let typeFile = type[i].toUpperCase();
        if (typeFile === extension.toUpperCase()) {
          console.log("type" + typeFile);
          existValue = true;
        }
      }
      if (existValue == true) {
        return null;
      } else {
        return {
          requiredFileType: true
        };
      }
      return null;
    }
    return null;
  };
}

component.ts

 this.addSlot
        .get("FileUpload")
        .setValidators([
          Validators.required,
          requiredFileType(["jpg", "png", "txt"])
        ]);

html

<div class="col-sm-5">
          <input
            type="file"
            formControlName="FileUpload"
            [class.is-invalid]="FileUpload.invalid && uploadPanel"
            class="form-control"
            (click)="handleFileInput($event.target.files)"
            #inputTypeFile
          />

          <!-- <button onclick="document.getElementById('abc').click()">
            choose file
          </button> -->
          <div *ngIf="FileUpload.invalid && uploadPanel">
            <small *ngIf="FileUpload.errors?.required" class="text-danger"
              >File is required</small
            >
            <small
              *ngIf="FileUpload.errors?.requiredFileType"
              class="text-danger"
              >File is required</small
            >
          </div>
        </div>