单击添加按钮时,角度选择多个文件而不上传和上传

Posted

技术标签:

【中文标题】单击添加按钮时,角度选择多个文件而不上传和上传【英文标题】:Angular select multiple files without uploading and upload when clicking add button 【发布时间】:2019-09-24 05:31:36 【问题描述】:

我有一个用于添加房屋的添加模式组件。当我按下添加房屋时,我会得到一个要填写的模式表格,并且有一个名为上传文件的按钮 我有一个上传组件,我可以在其中选择多个文件并上传。 比我必须填写其他信息并单击添加以添加房屋。 但我想选择文件而不直接上传它们,只有在我点击添加房屋按钮时才上传文件。

UploadComponent.ts

import  Component, OnInit, EventEmitter, Output  from '@angular/core';

import  HttpEventType, HttpClient  from '@angular/common/http';

@Component(
  selector: 'app-upload',
  templateUrl: './upload.component.html',
  styleUrls: ['./upload.component.scss']
)
export class UploadComponent implements OnInit 
  public imagePath;
  imgURL: any;
  public progress: number;
  public message: string;
  public files = []; @Output() public onUploadFinished = new EventEmitter();

  constructor(private http: HttpClient)  

  ngOnInit() 
  

  public uploadFile = (files: File[]) => 
    if (files.length === 0) 
      return;
    
    const formData = new FormData();
    for (let i = 0; i < files.length; i++) 
      const fileToUpload = files[i];
      formData.append('file', fileToUpload, fileToUpload.name);
    
    this.http.post('https://localhost:5001/api/upload', formData, reportProgress: true, observe: 'events')
    .subscribe(event => 
      if (event.type === HttpEventType.UploadProgress) 
        this.progress = Math.round(100 * event.loaded / event.total);
       else if (event.type === HttpEventType.Response) 
        this.message = 'Upload success.';
        this.onUploadFinished.emit(event.body);
      
    );


  // Preview image before upload
    const reader = new FileReader();
    this.imagePath = files;
    reader.readAsDataURL(files[0]);
    reader.onload = (_event) => 
    this.imgURL = reader.result;
  ;

  







上传组件.html

<div class="row" style="margin-bottom:15px;">
  <div class="col-md-3">
      <img [src]="imgURL"  *ngIf="imgURL">
    <input type="file" #file placeholder="Choose file" multiple (change)="uploadFile(file.files)" style="display:none;">
    <button type="button" class="btn btn-success" (click)="file.click()" >Upload File</button>
  </div>
  <div class="col-md-4">

  </div>
</div>

AddModalComponent.ts

import  Component, OnInit, ViewChild, TemplateRef  from '@angular/core';
import  FormControl, FormGroup, Validators, FormBuilder  from '@angular/forms';

import  BsModalService  from 'ngx-bootstrap';
import  HouseService  from 'app/services/house.service';
import  HttpEventType, HttpClient  from '@angular/common/http';
import  ModalService  from 'app/services/modal.service';
import  FormControlsService  from 'app/services/form-controls.service';

@Component(
  selector: 'app-add-modal',
  templateUrl: './add-modal.component.html',
  styleUrls: ['./add-modal.component.css']
)
export class AddModalComponent implements OnInit 


  public response: dbPath: '';
// Add Modal
@ViewChild('template') modal: TemplateRef<any>;

  constructor(
    public modalProp: ModalService,
    private modalService: BsModalService,
    private houseService: HouseService,
    private fb: FormBuilder,
    public fc: FormControlsService
    )  

  ngOnInit() 


    const validateImageUrl = '^(https?:\/\/.*\.(?:png|jpg))$';

    this.fc.name = new FormControl('', [Validators.required, Validators.maxLength(50)]);
    this.fc.price = new FormControl('', [Validators.required, Validators.min(0), Validators.max(10000)]);
    this.fc.description = new FormControl('', [Validators.required, Validators.maxLength(150)]);
    this.fc.imageUrl = new FormControl('', []);

    this.fc.insertForm = this.fb.group(

            name : this.fc.name,
            price : this.fc.price,
            description : this.fc.description,
            imageUrl : this.fc.imageUrl,
            avalaible : true,

            );


  


  onAddHouse() 
    this.modalProp.modalRef = this.modalService.show(this.modal);


public uploadFinished = (event) => 
  this.response = event;
  this.fc.imageUrl.setValue(this.response.dbPath);




 // Method to Add new Product
 onSubmit() 
  const newProduct = this.fc.insertForm.value;

  this.houseService.insertHouse(newProduct).subscribe(
      result => 
          this.houseService.clearCache();
          this.modalProp.houses$ = this.houseService.getHouses();

          this.modalProp.houses$ .subscribe(newlist => 
              this.modalProp.houses = newlist;
              this.modalProp.modalRef.hide();
              this.fc.insertForm.reset();
              // this.rerender();

              );





          console.log('New Product added');

      ,
      error => console.log('Could not add Product')

      );






AddModalComponent.html



<!-- ADD HOUSE MODAL START-->
<button class="btn btn-warning mb-3 float-right text-uppercase" *ngIf="modalProp.userRoleStatus == 'Admin'" (click)="onAddHouse()" ><i class="fa fa-plus"></i> Huis toevoegen</button><br>

<ng-template #template>
  <div class="modal-header">
    <h4 class="modal-title">ADD NEW HOUSE</h4>
    <button type="button" class="close pull-right" aria-label="Close" (click)="modalProp.modalRef.hide()">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body text-center">
    <p class="list-group-item active text-center text-uppercase"></p>
    <form [formGroup]="fc.insertForm" (ngSubmit)="onSubmit()">
      <ul class="list-group">
        <li class="list-group-item">
          <div class="input-group">
            <div class="input-group-prepend">
              <span class="input-group-text" id="houseTitle"><i class="fa fa-pencil-square-o"></i></span>
            </div>
            <input type="text" id="name" formControlName="name" class="form-control" placeholder="Stad" aria-label="name" aria-describedby="houseTitle">
          </div>
          <div *ngIf="fc.name.touched && fc.name.errors" class="errorMessage" >
            <span *ngIf="fc.name.hasError('required')">City Name is required.</span>
            <span *ngIf="fc.name.hasError('maxlength')">Only 50 characters allowed for House Name.</span>
          </div>
        </li>
        <li class="list-group-item">
          <div class="input-group">
            <div class="input-group-prepend">
              <span class="input-group-text" id="houseDescription"><i class="fa fa-pencil-square-o"></i></span>
            </div>
            <textarea formControlName="description" class="form-control" placeholder="Beschrijf het huis - Max 150 Tekens" aria-label="Description" aria-describedby="houseDescription"></textarea>
          </div>
          <div class="errorMessage" *ngIf="fc.description.touched && fc.description.errors">
            <span *ngIf="fc.description.hasError('required')">House Description is required.</span>
            <span *ngIf="fc.description.hasError('maxlength')">Only 150 characters allowed for House Description.</span>
          </div>
        </li>
        <!-- <li class="list-group-item">
          <div class="input-group">
            <div class="input-group-prepend">
              <div class="input-group-text">
                <input type="checkbox" formControlName="available" checked aria-label="Checkbox for following text input">
              </div>
            </div>
            <input type="text" class="form-control" placeholder="House available" disabled>
          </div>
        </li> -->
        <li class="list-group-item">
          <div class="input-group">
            <div class="input-group-prepend">
              <span class="input-group-text"><i class="fa fa-usd"></i></span>
            </div>
            <input formControlName="price" type="text" class="form-control" placeholder="Prijs">
          </div>
          <div class="errorMessage" *ngIf="fc.price.touched && fc.price.errors">
            <span *ngIf="fc.price.hasError('required')">House Price is required.</span>
            <span *ngIf="fc.price.hasError('min')" >Negative price Not allowed</span>
            <span *ngIf="fc.price.hasError('max')">Max price allowes is 10000</span>
          </div>
        </li>
        <li class="list-group-item">

          <app-upload (onUploadFinished)="uploadFinished($event)"></app-upload>
        </li>
        <li class="list-group-item">
          <button  [disabled]="fc.insertForm.invalid" class="btn btn-primary btn-block">ADD</button>
        </li>
      </ul>

    </form>

  </div>
</ng-template>

<!-- ADD HOUSE MODAL START-->

【问题讨论】:

【参考方案1】:

使用 Angular 上传多个文件:

在组件(TS)中声明选择的文件属性(我们稍后会用到):

export class SomeComponent 
  selectedFile: FileList | [] = [];
  //...

这是图片上传的 HTML:

<form>
  <input
    style="display: none"
    type="file" name="images" (change)="onFileChanged($event)" #fileInput multiple="multiple">
  <button type="button" (click)="fileInput.click()">Select Files</button>
  <button type="button" (click)="onUpload()">Upload!</button>
</form>

注意style="display: none"是隐藏字段,所以只有按钮可见。

#fileInput 指向输入元素并被按钮用于在单击按钮时单击元素:fileInput.click()

返回组件:

  onFileChanged(event: any) 
    this.selectedFiles = event.target.files;
    console.log(this.selectedFiles);
  

  onUpload() 
    //Here you send 'this.selectedFiles' to the server..
  

TL;DR(太长;未阅读)

这部分真正使多个文件上传可用的是: 输入字段上的multiple="multiple"

【讨论】:

【参考方案2】:

您可以只使用一个简单的数组来推送文件,然后在提交时迭代该数组并进行发布...

filesToUpload = [];

// called on file chosen
handleFileInput(files: FileList) 
  this.filesToUpload.push(files[0]);

并在提交迭代文件并制作表单数据时,或者使用forkJoin 并行运行请求。

const reqs = [];
this.filesToUpload.forEach(x => 
  const formData = new FormData();
  formData.append('file', x);
  // add your function
  reqs.push(this.myService.doSomething(formData)));
);

forkJoin(reqs).subscribe(......)

【讨论】:

以上是关于单击添加按钮时,角度选择多个文件而不上传和上传的主要内容,如果未能解决你的问题,请参考以下文章

如何以 POST 请求的形式上传单独选择的文件? [复制]

当用户单击“打开”时上传文件输入表单

用图像替换正常的文件上传输入

如何使用添加按钮在 Angular 6 中上传多个文件?

将多个图像上传到 Firebase

Vaadin:上传按钮监听器