【问题标题】:Angular 7 : How do I submit file/image along with my reactive form?Angular 7:如何提交文件/图像以及我的反应形式?
【发布时间】:2019-03-19 13:31:12
【问题描述】:

我已经创建了带有文本输入的简单反应式表单,当提交表单时,我想传递来自文件输入的图像。每次我谷歌我都会得到教程,他们告诉我如何上传文件,但它是在没有其他输入字段的情况下完成的。我了解如何做到这一点,我不明白如何在一次提交中同时提交我的表单和文件输入。

在我的场景中,我不应该使用响应式表单而是简单的new FormData() 并将每个输入附加到其中吗?

如果我能做到,请给我一个简单的例子。

编辑:How to include a file upload control in an Angular2 reactive form? 这不是答案。答案市场没有随反应形式发布文件,它是单独发布文件。

【问题讨论】:

标签: angular angular-reactive-forms angular-forms


【解决方案1】:

也有这个问题,我做的是构造一个FormData,使用循环将formGroup值添加到表单数据中

import {
  Component,
  OnInit,
  ChangeDetectorRef
} from '@angular/core';
import {
  FormGroup,
  FormBuilder,
  Validators
} from '@angular/forms';


export class TodoFormComponent {
  todoForm: FormGroup = this.fb.group({
    todo: ['', Validators.required],
    image: ['', Validators.required], //making the image required here
    done: [false]
  })

  constructor(
    private fb: FormBuilder,
    private cd: ChangeDetectorRef
  ) {}

  /**
   *@param event {EventObject} - the javascript change event
   *@param field {String} - the form field control name
   */
  onFileChange(event, field) {
    if (event.target.files && event.target.files.length) {
      const [file] = event.target.files;
      // just checking if it is an image, ignore if you want
      if (!file.type.startsWith('image')) {
        this.todoForm.get(field).setErrors({
          required: true
        });
        this.cd.markForCheck();
      } else {
        // unlike most tutorials, i am using the actual Blob/file object instead of the data-url
        this.todoForm.patchValue({
          [field]: file
        });
        // need to run CD since file load runs outside of zone
        this.cd.markForCheck();
      }
    }

    onSubmit() {
      const formData = new FormData();
      Object.entries(this.todoForm.value).forEach(
        ([key, value]: any[]) => {
          formData.set(key, value);
        }

        //submit the form using formData
        // if you are using nodejs use something like multer
      )
    }

  }
<form [formGroup]="todoForm" (ngSubmit)="onSubmit()">
  <input type="file" formControlName="image" (onchange)="onFileChange($event, 'image')"/>
  <textarea formControlName="todo"></textarea>
  <button type="submit">Submit</button>
</form>

在服务器端,您可以像处理表单数据请求一样处理请求

【讨论】:

    【解决方案2】:

    文件是二进制数据,表单字段通常是 ​​json 文本文件。为了将它们都放在一篇文章中,您必须将其中一个数据转换为另一个数据。我通过将文件转换为 base64 字符串然后将其添加到普通 json 数据来做到这一点。显然,您必须将 base64 字符串转换回文件,但大多数环境(例如 C#)可以直接执行此操作。

    这里是一些代码,以便向您展示我是如何做到的:

    Html(这是文件按钮,你必须使用它来让你的浏览器允许你从文件系统中选择一个文件):

    <input name="imageUrl" type="file" [accept]="filePattern" multiple=""
                                    (change)="handleInputChange($event)" />
    

    .ts:

        handleInputChange(e) {
        const file = e.dataTransfer ? e.dataTransfer.files[0] : e.target.files[0];
        const reader = new FileReader();
    
        const fileDto: Partial<IFileSaveDto> = {
            // your other data here
            title: 'what ever here',
            fileAsBase64: null
        };
    
        reader.onload = (ev: ProgressEvent) => {
            fileDto.fileAsBase64 = reader.result;
        };
    
        reader.readAsDataURL(file);
    }
    

    这种方法的缺点是,base64 会产生相当多的开销。如果您要上传非常大或很多文件,这不是一个好方法。

    这是一个完整的解释示例:https://nehalist.io/uploading-files-in-angular2/

    【讨论】:

      猜你喜欢
      • 2019-08-20
      • 1970-01-01
      • 2021-06-29
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 2019-07-07
      • 2020-02-24
      • 1970-01-01
      相关资源
      最近更新 更多