【问题标题】:.net core 2.2 & Angular 7: IFormFile in file upload controller is always null.net core 2.2 & Angular 7:文件上传控制器中的 IFormFile 始终为空
【发布时间】:2019-07-27 06:07:56
【问题描述】:

当查看其他答案和一些谷歌时,一切似乎都很好,但我的控制器从未收到任何数据。

Api uris 等正确,请求到达正确的控制器

角度 sn-p:

component.html - 我的输入字段

<div class="input-group">
    <input type="file" #fileInput id="fileInput" (change)="stageFile()"
           accept="csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel">
    <div class="input-group-append">
        <button class="btn btn-primary" type="button" (click)="fileUpload()" [disabled]="!staged || uploading">
          <span *ngIf="!uploading,else loadAnim">Upload</span>
          <ng-template #loadAnim>Uploading...</ng-template>
        </button>
    </div>
</div>

component.ts - 从视图中获取数据

@ViewChild('fileInput') fileInput;
private file: File;
public uploading = false;
public staged = false;

constructor(private uploadService: UploadService) { }

public stageFile(): void {
    this.staged = true;
    this.file = this.fileInput.nativeElement.files[0];
    console.log(this.file)
}

public fileUpload():void {
    this.uploading = true;
    if (this.file != null)
      this.uploadService.upload(this.file).subscribe();
    this.staged = false;
    this.uploading = false;
}

services.ts - 处理实际的 ajax 调用

private uploadURI = environment.dataServiceURI + '/upload';

constructor(private http: HttpClient) {}

public upload(file: File): Observable<object> {
// create multipart form for file
let formData: FormData = new FormData();
formData.append('file', file, file.name);

const headers = new HttpHeaders().append('Content-Type', 'mulipart/form-data');

// POST
return this.http
  .post(this.uploadURI, formData, {headers: headers})
  .pipe(map(response => response));
}

.net core sn-p

这里 IFormFile 文件总是包含 null,因此我的结果总是 500

[HttpPost("upload")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult ParseData([FromForm(Name = "file")] IFormFile file)
{
    if (file == null)
       return StatusCode(500);
    (...)
    return Ok()
 }

请求负载信息

来自浏览器网络

------WebKitFormBoundarycBigaNKzS4qNcTBg 
Content-Disposition: form-data; name="file"; filename="test_data_schema.xlsx" 
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

------WebKitFormBoundarycBigaNKzS4qNcTBg--

【问题讨论】:

  • 当您查看浏览器的网络选项卡时,它会发送您的文件吗?只是为了检查问题是来自您的前端还是后端......
  • 是的,它似乎发送了文件,至少请求有效负载包含一个 Content-Disposition 和一个 Content-Type 以及正确的表单数据值。即使有效载荷是空的,我也不知道为什么。有什么方法可以检查它是否真的发送文件而不仅仅是文件名?在发送之前将文件记录到控制台会给我一个以字节为单位的大小,但这就是我得到的全部。
  • 您的代码中有一个错字: const headers = new HttpHeaders().append('Content-Type', 'mulipart/form-data'); --> “多部分”
  • 我检查了我的 dotnet 代码: public Task Backup(IFormFile file) 也许你应该删除 FromForm 选项,因为它是基于约定的(有效负载中的'file'将匹配参数中的'file' )
  • 为我的错误提供资金(感谢@hugo)我仔细查看了我的标题,不仅有错字,还有错误。它必须是 Content-Disposition 而不是 Content-Type

标签: angular asp.net-core asp.net-core-webapi


【解决方案1】:

问题已解决:

service.ts中应该是

const headers = new HttpHeaders().append('Content-Disposition', 'multipart/form-data');

而不是

const headers = new HttpHeaders().append('Content-Type', 'multipart/form-data');

同样在 .net 控制器 中,添加或删除 [FromForm(Name = "file")] 作为参数前缀不会改变行为。无论有没有它,它都可以正常工作。正如 hugo 在 cmets 中指出的那样,只要参数名称与表单数据中的名称匹配,它就是基于约定的。

【讨论】:

  • 感谢它的帮助。知道如何将其他模型属性与文件一起发送吗?现在我将每个模型属性附加到 FormData 对象,我认为这不是一个好习惯
【解决方案2】:

同意,Content-Disposition 标头确实有帮助。还要满足一个条件:formData.append(....) 方法的第一个参数: 的第一个参数

formData.append(...)

方法:

应该与 控制器动作中的agrument名称:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    相关资源
    最近更新 更多