Angular 5 file upload: Failed to set the 'valu

2020-04-02 09:53发布

I have a form for uploading a file in an angular 5 app, and as I have copied it exactly from a code I had written a while ago, I can swear it had worked before.

Here is my HTML code:

<form [formGroup]="form" (ngSubmit)="onSubmit()">
        <div class="form-group">
            <label>File:</label>
            <input #theFile type="file" (change)="onFileChange($event)" accept=".png" class="form-control" 
                    formControlName="content" />
            <input type="hidden" name="fileHidden" formControlName="imageInput"/>

                    <!-- [(ngModel)]="model.content" -->

            <div class="alert alert-danger" *ngIf="!form.prestine && form.controls.content.errors?.noFile">
                Please provide a photo.
            </div>
            <div class="alert alert-danger" *ngIf="form.controls.content.errors?.fileTooBig">
                The file is too big and won't uploaded. Maximum allowed size is 500kb.
            </div>
        </div>
        <div class="form-group">
            <label>Notes</label>
            <textarea type="text" class="form-control" formControlName="notes" [(ngModel)]="model.notes" > </textarea>
        </div>
        <button type="submit" class="btn btn-primary" [disabled]="!form.valid">Submit</button>
        <button class="btn btn-default" type="button" (click)="close(false);">Cancel</button>
    </form>

Here is the "onFileChange" method used in the fileUpload control:

onFileChange($event)
  {
    if ($event.target.files.length > 0)
    {
        let ftu: File = null;
        ftu = $event.target.files[0];
        this.form.controls['content'].setValue(ftu);
        this.model.content = $event.target.files[0];
    }
  }

and here is the code for the custom validator I have written and used:

import { FormControl } from '@angular/forms';

export class SekaniRootImageValidators
{
    static sizeTooBig(control: FormControl)
    {
        if (!control.value)
        {
            return { noFile : true }
        }
        else  if (control.value[0].size > 505000)
        {
            return { fileTooBig: true}
        }
        return null;

    }
}

Now the issue is as soon as I select a file in the input control, I get this error message in the console:

ERROR DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

This code has worked before, so I have no idea where to even start. Any help is appreciated!

ATTENTION: Here is a link to a working answer: Angular2: validation for <input type="file"/> won't trigger when changing the file to upload

3条回答
我想做一个坏孩纸
2楼-- · 2020-04-02 10:21

Like the error is saying, you can only set an empty string to a file input value to clear the selection. It could open security risks otherwise. I can't imagine how that code could've ever worked. Maybe in some non-standard (bad) browser?

Shouldn't that code work if you just remove the line, why do you need to set the same value to the input that it already has anyway?

Edit: seems a custom ValueAccessor is needed for validating file inputs. Solution in another answer: Angular2: validation for <input type="file"/> won't trigger when changing the file to upload

查看更多
乱世女痞
3楼-- · 2020-04-02 10:26

In my case I just removed the formControlName:

<input type="file" (change)="onFileChange($event)">

And .ts:

onFileChange(event) {
    const reader = new FileReader();

    if (event.target.files && event.target.files.length) {
      const [file] = event.target.files;
      reader.readAsDataURL(file);
      reader.onload = () => {
        this.data.parentForm.patchValue({
          tso: reader.result
        });

        // need to run CD since file load runs outside of zone
        this.cd.markForCheck();
      };
    }
  }
查看更多
女痞
4楼-- · 2020-04-02 10:30

Do not set the value of the input property to the selected file. Instead just set the file content into a variable and append to the request object separately. For the file input , just assign the even.target.value as the input value, so the user see the actual file selected.

查看更多
登录 后发表回答