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

Angular 18与.NET 8文件上传问题咨询及方案疑问

文件上传问题:Angular 18 → .NET 8 Web API(存AWS S3)

我尝试从Angular 18应用向.NET 8 Web API上传文件(最终通过服务存入AWS S3桶),但上传失败。用Postman调用API时,控制器能正常识别文件名;但通过Angular应用上传时,控制器始终显示文件数量为0。网络面板和控制台能看到请求已提交FormData,但控制器就是接收不到任何文件。

核心疑问:是否必须将文件Base64编码后传给API再写入S3?还是可以直接用FormData提交文件到API并存入S3?


Angular 18 相关代码

upload.component.html

<div class="card mb-4">
  <div class="card-header">
    <strong>Upload</strong>
  </div>
  <div class="card-body">
    <div class="upload-section mb-3">
      <label for="fileUpload" class="form-label">Select File</label>
      <input
        type="file"
        id="fileUpload"
        (change)="onFileSelected($event)"
        class="form-control"
        multiple
      />
    </div>
    <div class="d-flex justify-content-end">
      <button
        type="button"
        class="btn btn-primary me-2"
        (click)="uploadDocuments()"
      >
        Upload
      </button>
      <button
        type="button"
        class="btn btn-secondary"
        (click)="resetDocuments()"
      >
        Reset
      </button>
    </div>
  </div>
</div>

upload.component.ts

onFileSelected(event: any) {
  if (event.target.files && event.target.files.length > 0) {
    const files: FileList = event.target.files;
    for (let i = 0; i < files.length; i++) {
      this.selectedDocuments.push(files[i]);
    }
  }
}

uploadDocuments() {
  if (this.selectedDocuments.length > 0) {
    this.uploadProgress = 0; // Reset progress
    this.documentService.uploadDocuments(this.selectedDocuments).subscribe({
      next: (event) => {
        if (event.type === HttpEventType.UploadProgress && event.total) {
          this.uploadProgress = Math.round((100 * event.loaded) / event.total);
        } else if (event instanceof HttpResponse) {
          console.log('Documents uploaded successfully:', event.body);
          alert('Documents uploaded successfully!');
          this.selectedDocuments = []; // Clear the list after uploading
          this.uploadProgress = 0; // Reset progress
        }
      },
      error: (error) => {
        console.error('Error uploading documents:', error);
        alert('An error occurred during document upload.');
      }
    });
  } else {
    alert('There are no documents selected for upload.');
  }
}

upload.service.ts

uploadDocuments(files: File[]): Observable<HttpEvent<any>> {
    const formData = new FormData();
    files.forEach(file => {
      formData.append('files', file, file.name);
    });
    console.log('FormData:', formData); // Just to check the formData contents

    formData.forEach((value, key) => {
      console.log(`Key: ${key}, Value:`, value);
    });
    console.log('FormData size:', formData.getAll('files').length);

    const req = new HttpRequest('POST', `${this.apiUrl}/documents/upload`, formData, {
      reportProgress: true,  // Enable progress tracking
      responseType: 'json'
    });

    return this.http.request(req).pipe(
      catchError(this.handleError) // Handle errors properly
    );
}

.NET 8 Web API 控制器代码

[HttpPost("upload"), DisableRequestSizeLimit]
public async Task<IActionResult> UploadDocuments([FromForm] IFormFileCollection files)
{
    if (files.Count == 0)
    {
        return BadRequest("No files selected.");
    }
    await _documentService.UploadDocumentsAsync(files, GetOrganizationName());
    return Ok("Files uploaded successfully.");
}

问题解答

核心结论

完全不需要Base64编码,直接用FormData提交文件到API再存入S3是可行的——Postman能成功就是最好的证明。你的问题出在Angular请求配置或跨域设置上,以下是具体排查和修复方向:

  1. 不要手动设置Content-Type
    Angular发送FormData时会自动添加multipart/form-data头并生成正确的boundary值,手动设置这个头会破坏请求结构,确保你的代码没加类似headers: {'Content-Type': 'multipart/form-data'}的配置。

  2. 检查跨域(CORS)配置
    .NET后端的CORS策略必须允许表单数据上传,在Program.cs中确保配置包含:

    builder.Services.AddCors(options =>
    {
        options.AddPolicy("AllowAngular", policy =>
        {
            policy.WithOrigins("你的Angular应用地址")
                  .AllowAnyHeader()
                  .AllowAnyMethod()
                  .AllowCredentials();
        });
    });
    
    app.UseCors("AllowAngular");
    
  3. 确认参数名严格匹配
    你的FormData键是files,后端参数也是files,这部分没问题,但要检查是否有大小写或拼写错误。

  4. 调整文件大小限制
    虽然加了DisableRequestSizeLimit,大文件上传还需在appsettings.json补充配置:

    "Kestrel": {
        "Limits": {
            "MaxRequestBodySize": 52428800 // 50MB,按需调整
        }
    }
    
  5. 验证实际请求内容
    在浏览器Network面板查看请求的FormData部分,确认文件是否真的被包含在请求体里——控制台打印FormData可能显示不全,实际请求内容才是准确依据。

正确流程

确认上述配置无误后,直接用FormData提交文件,后端接收IFormFileCollection,然后将文件流直接传给AWS S3 SDK(比如PutObjectAsync)即可,Base64编码会让文件体积增大30%,完全没必要。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:00:08