You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中如何通过代码设置文件输入框的已选文件名?

问题

我有一个带模态对话框的Angular应用,模态框内包含文件输入字段及“Next”和“Back”按钮。选择文件后进入下一个视图,返回上传文件对话框时,希望在输入框中显示之前选中的文件,但目前出现以下错误:

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.

相关代码如下:

<ds-modal>

  <ds-box-content>
        <ds-form-field>
          <label ds-label for="file">Excel-File</label>
          <input ds-input
                 #fileInput
                 id="file"
                 type="file"
                 formControlName="file"
                 [accept]="acceptFileType"
                 [labellingConfig]="labellingConfig"
                 (change)="extractUploadedFile($event)"
                 required
          />
        </ds-form-field>
  </ds-box-content>
  
    <button
      ds-button
      *ngIf="showBackButton$ | async"
      [variant]="'outline'"
      class="modal-button"
      (click)="onBackClick()"
    >
      Back
    </button>
</ds-modal>
export class MyComponent implements OnInit, AfterViewInit {
  @ViewChild('fileInput') fileInputRef!: ElementRef;

  maxSize = 10;
  acceptFileType: string = '.xlsx';
  labellingConfig: DsInputLabellingConfig = {
    empty: 'No File selected',
    addFilesSingle: 'Add file',
    fileCounter: '',
    addFilesMultiple: ''
  };

  selectedFileType: string = FileTypeEnum.EXCEL;

  reactiveForm = new FormGroup({
    file: new FormControl('', {
      validators: [Validators.required],
    })
  });


  uploadedXlsxFile?: File;

  onBackClick() {
    this.selectedFileType = this.savedFileType ?? FileTypeEnum.EXCEL;
    this.uploadedXlsxFile = this.savedUploadedXlsxFile;
    if (this.uploadedXlsxFile) {
      this.reactiveForm.controls['file'].setValue(this.uploadedXlsxFile.name);
    } else {
      this.reactiveForm.controls['file'].reset();
    }

  }

}
解决方案

浏览器出于安全限制,禁止通过代码直接设置type="file"输入框的value(仅允许设为空字符串),因此无法通过表单控件赋值来显示历史选中的文件名。推荐以下两种实现方式:

1. 利用组件自带的labellingConfig自定义显示文本

你的ds-input组件支持labellingConfig配置,返回上传视图时,直接修改配置文本为已选中的文件名即可:

onBackClick() {
  this.selectedFileType = this.savedFileType ?? FileTypeEnum.EXCEL;
  this.uploadedXlsxFile = this.savedUploadedXlsxFile;
  
  if (this.uploadedXlsxFile) {
    // 更新配置,用文件名替换空状态提示
    this.labellingConfig = {
      ...this.labellingConfig,
      empty: this.uploadedXlsxFile.name
    };
    // 表单控件直接绑定文件对象,而非文件名
    this.reactiveForm.controls['file'].setValue(this.uploadedXlsxFile);
  } else {
    // 恢复默认提示文本
    this.labellingConfig = {
      ...this.labellingConfig,
      empty: 'No File selected'
    };
    this.reactiveForm.controls['file'].reset();
  }
}

同时在文件选择方法中保存文件对象和类型:

extractUploadedFile(event: Event) {
  const input = event.target as HTMLInputElement;
  if (input.files?.length) {
    this.uploadedXlsxFile = input.files[0];
    this.savedUploadedXlsxFile = this.uploadedXlsxFile;
    this.savedFileType = this.selectedFileType;
    // 选中文件后立即更新显示文本
    this.labellingConfig = {
      ...this.labellingConfig,
      empty: this.uploadedXlsxFile.name
    };
    this.reactiveForm.controls['file'].setValue(this.uploadedXlsxFile);
  }
}

2. 隐藏原生输入,自定义UI展示

如果组件配置不够灵活,可以隐藏原生文件输入框,用自定义元素显示文件名,点击时触发原生选择逻辑:

  • 修改模板:
<ds-form-field>
  <label ds-label for="file">Excel-File</label>
  <!-- 隐藏原生文件输入 -->
  <input ds-input
         #fileInput
         id="file"
         type="file"
         formControlName="file"
         [accept]="acceptFileType"
         (change)="extractUploadedFile($event)"
         required
         style="display: none;"
  />
  <!-- 自定义可点击的显示区域 -->
  <div ds-input (click)="fileInputRef.nativeElement.click()" style="cursor: pointer;">
    {{ uploadedXlsxFile?.name || 'No File selected' }}
  </div>
</ds-form-field>
  • 组件逻辑只需确保uploadedXlsxFile在返回时被正确恢复即可,无需修改表单值的设置逻辑。

关键注意点

  • 提交表单时,直接使用保存的uploadedXlsxFile对象,不要依赖表单控件的value(原生file输入的value无法被代码正确设置)。
  • 仅能通过用户手动选择文件更新uploadedXlsxFile,代码中只能恢复该对象的引用,不能通过设置输入框value实现回显。

内容的提问来源于stack exchange,提问作者LDropl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:07:01