Angular 5 文件上传:无法在"HTMLInputElement"上设置"value"属性



我有一个用于在 angular 5 应用程序中上传文件的表单,并且由于我完全是从我不久前编写的代码中复制的,我可以发誓它以前曾经工作过。

这是我的HTML代码:

<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>

下面是 fileUpload 控件中使用的"onFileChange"方法:

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];
}
}

这是我编写和使用的自定义验证器的代码:

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;
}
}

现在的问题是,一旦我在输入控件中选择一个文件,我就会在控制台中收到以下错误消息:

错误圆顶感知:无法将"值"属性设置为 "HTMLInputElement":此输入元素接受文件名,该文件名可能 仅以编程方式设置为空字符串。

这段代码以前工作过,所以我不知道从哪里开始。任何帮助不胜感激!

注意:这是指向有效答案的链接:Angular2:更改要上传的文件时不会触发<输入类型 />的验证

就我而言,我刚刚删除了表单控件名称:

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

和 .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();
};
}
}

就像错误所说的那样,您只能将空字符串设置为文件输入值以清除选择。否则,它可能会带来安全风险。我无法想象这段代码是如何工作的。也许在某些非标准(坏)浏览器中?

如果您只是删除该行,该代码不应该起作用吗,为什么您需要为它已经具有的输入设置相同的值?

编辑:似乎需要一个自定义的价值访问器来验证文件输入。另一个答案的解决方案:Angular2:更改要上传的文件时不会触发<输入类型 />的验证

首先,您应该从类型文件的元素中删除"formControlName", 因为它得到的字符串 然后在您的 TS 文件中您应该添加这个

if (event.target.files && event.target.files.length > 0) {
const file = (event.target.files[0] as File);
this.yourForm.get('image').setValue(file);
console.log(this.yourForm.get('image').value);
}

通过为文件提供 2 个输入来实现这一点。这是我是如何做到的:

this.myForm= this.formBuilder.group({
fileSource: ['', Validators.required],
fileName: '',
})

.HTML

<input type="file" formControlName='fileSource' (change)="onFileSelected($event)"/>

打字稿

onFileSelected(event) {
if(event.target.files.length > 0) 
{
this.myForm.patchValue({
fileName: event.target.files[0],
})
}
}
submit(){
const formData = new FormData();
formData.append('file', this.myForm.get('fileName').value);

this.http.post('http://localhost:3000/upload', formData)
.subscribe(res => {
console.log(res);
alert('Uploaded Successfully.');
})
}

不要将输入属性的值设置为所选文件。相反,只需将文件内容设置为变量并单独附加到请求对象。 对于文件输入,只需分配 even.target.value 作为输入值,以便用户看到选择的实际文件。

最新更新