c# - 如何将文件从 Angular 上传到 ASP.NET Core Web API

标签 c# angular typescript asp.net-core angular8

有人问过类似的问题,但在浏览了所有这些问题和许多关于该主题的博客文章后,我无法弄清楚这一点,所以请原谅我。

我正在创建一个简单的博客(出于这个问题的目的)两部分,Angular 8 中的前端 SPA 和 ASP.NET Core 3 中的后端 API。在我前端的一部分中,我试图上传用作新创建博客的图像的图像。当我尝试上传图像时,后端生成的 IFormFile 总是输出到 null .以下是代码,非常感谢任何帮助!

新博客.component.html:

<form [formGroup]="newBlogForm" (ngSubmit)="onSubmit(newBlogForm.value)">

    <div>
        <label for="Name">
            Blog Name
        </label>
        <input type="text" formControlName="Name">
    </div>

    <div>
        <label for="TileImage">
            Tile Image
        </label>
        <input type="file" formControlName="TileImage">
    </div>

    <button type="submit">Create Blog</button>

</form>

新博客.component.ts:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormControl } from '@angular/forms';
import { BlogService } from '../blog-services/blog.service';

@Component({
  selector: 'app-new-blog',
  templateUrl: './new-blog.component.html',
  styleUrls: ['./new-blog.component.css']
})
export class NewBlogComponent implements OnInit {
  private newBlogForm: FormGroup;

  constructor(private formBuilder: FormBuilder, private blogService: BlogService) { }

  ngOnInit() {
    this.newBlogForm = this.formBuilder.group({
      Name: new FormControl(null),
      TileImage: new FormControl(null)
    });
  }

  onSubmit(blogData: FormData) {
    console.log('new blog has been submitted.', blogData);
    this.blogService.postBlog(blogData);
    this.newBlogForm.reset();
  }

}
postBlog来自 blog.service.ts:
  postBlog(blogData: FormData): Observable<any> {
    const postBlogSubject = new Subject();
    this.appOptions.subscribe(
      (options) => {
        const url = options.blogAPIUrl + '/Blogs';
        this.http
          .post(url, blogData)
          .subscribe(
            (blog) => {
              postBlogSubject.next(blog);
            }
          );
      }
    );
    return postBlogSubject.asObservable();
  }

我的 BlogController 的签名如下所示:

[HttpPost]
public async Task<ActionResult<Blog>> PostBlog([FromForm]PostBlogModel blogModel)

与 PostBlogModel 如下:

    public class PostBlogModel
    {
        public string Name { get; set; }
        public IFormFile TileImage { get; set; }
    }

我已经实现了日志中间件来尝试调试。输出如下(我看到由于某种原因,前端正在发送 application/json 而不是 multipart/form-data 但我不确定为什么或如何修复......)
blogapi_1  | info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
blogapi_1  |       Request finished in 170.16740000000001ms 500
blogapi_1  | info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
blogapi_1  |       Request starting HTTP/1.1 OPTIONS http://localhost:5432/api/v1/Blogs
blogapi_1  | dbug: BlogAPI.Middleware.RequestResponseLoggingMiddleware[0]
blogapi_1  |       HTTP Request: Headers:
blogapi_1  |            key: Connection, values: keep-alive
blogapi_1  |            key: Accept, values: */*
blogapi_1  |            key: Accept-Encoding, values: gzip, deflate, br
blogapi_1  |            key: Accept-Language, values: en-US,en-IN;q=0.9,en;q=0.8,en-GB;q=0.7
blogapi_1  |            key: Host, values: localhost:5432
blogapi_1  |            key: Referer, values: http://localhost:5431/blog/new-blog
blogapi_1  |            key: User-Agent, values: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
blogapi_1  |            key: Origin, values: http://localhost:5431
blogapi_1  |            key: Access-Control-Request-Method, values: POST
blogapi_1  |            key: Access-Control-Request-Headers, values: content-type
blogapi_1  |            key: Sec-Fetch-Site, values: same-site
blogapi_1  |            key: Sec-Fetch-Mode, values: cors
blogapi_1  |
blogapi_1  |        type:
blogapi_1  |        scheme: http
blogapi_1  |        host+path: localhost:5432/api/v1/Blogs
blogapi_1  |        queryString:
blogapi_1  |        body: 
blogapi_1  | info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
blogapi_1  |       CORS policy execution successful.
blogapi_1  | dbug: BlogAPI.Middleware.RequestResponseLoggingMiddleware[0]
blogapi_1  |       HTTP Response: Headers:
blogapi_1  |            key: Access-Control-Allow-Headers, values: Content-Type
blogapi_1  |            key: Access-Control-Allow-Origin, values: http://localhost:5431
blogapi_1  |
blogapi_1  |        statusCode: 204
blogapi_1  |        responseBody: 
blogapi_1  | info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
blogapi_1  |       Request finished in 58.5088ms 204
blogapi_1  | info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
blogapi_1  |       Request starting HTTP/1.1 POST http://localhost:5432/api/v1/Blogs application/json 56
blogapi_1  | dbug: BlogAPI.Middleware.RequestResponseLoggingMiddleware[0]
blogapi_1  |       HTTP Request: Headers:
blogapi_1  |            key: Connection, values: keep-alive
blogapi_1  |            key: Content-Type, values: application/json
blogapi_1  |            key: Accept, values: application/json, text/plain, */*
blogapi_1  |            key: Accept-Encoding, values: gzip, deflate, br
blogapi_1  |            key: Accept-Language, values: en-US,en-IN;q=0.9,en;q=0.8,en-GB;q=0.7
blogapi_1  |            key: Host, values: localhost:5432
blogapi_1  |            key: Referer, values: http://localhost:5431/blog/new-blog
blogapi_1  |            key: User-Agent, values: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
blogapi_1  |            key: Origin, values: http://localhost:5431
blogapi_1  |            key: Content-Length, values: 56
blogapi_1  |            key: Sec-Fetch-Site, values: same-site
blogapi_1  |            key: Sec-Fetch-Mode, values: cors
blogapi_1  |       
blogapi_1  |        type: application/json
blogapi_1  |        scheme: http
blogapi_1  |        host+path: localhost:5432/api/v1/Blogs
blogapi_1  |        queryString:
blogapi_1  |        body: {"Name":"test","TileImage":"C:\\fakepath\\DSC_0327.jpg"}

最佳答案

my BlogController looks like this:

[HttpPost]

public async Task<ActionResult<Blog>> PostBlog([FromForm]PostBlogModel blogModel)

看来你是想用form-data来传递数据,实现可以引用下面的代码示例。
.component.html
<form [formGroup]="newBlogForm" (ngSubmit)="onSubmit(newBlogForm.value)">

  <div>
      <label for="Name">
          Blog Name
      </label>
      <input type="text" formControlName="Name">
  </div>

  <div>
      <label for="TileImage">
          Tile Image
      </label>
      <input type="file" formControlName="TileImage" (change)="onSelectFile($event)" >
  </div>

  <button type="submit">Create Blog</button>

</form>
.component.ts
selectedFile: File = null;
private newBlogForm: FormGroup;
constructor(private http: HttpClient) { }

ngOnInit() {
  this.newBlogForm = new FormGroup({
    Name: new FormControl(null),
    TileImage: new FormControl(null)
  });
}

onSelectFile(fileInput: any) {
  this.selectedFile = <File>fileInput.target.files[0];
}

onSubmit(data) {
  
  const formData = new FormData();
  formData.append('Name', data.Name);
  formData.append('TileImage', this.selectedFile);

  this.http.post('your_url_here', formData)
  .subscribe(res => {

    alert('Uploaded!!');
  });

  this.newBlogForm.reset();
}
测试结果
enter image description here

关于c# - 如何将文件从 Angular 上传到 ASP.NET Core Web API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59349595/

相关文章:

c# - 应该如何在 XML 中解释带有 CDATA 和空格的文本节点?

c# - 我应该模拟框架类吗

angular - 如何在我的 Angular 应用程序中使用 Firebase Admin SDK?

angular - 如何在rxjs中开始后停止间隔

javascript - 是否可以定义一个包含对象的对象?

c# - 在 C# 中将字符强行插入文本框

c# - 我应该抛出自己的 ArgumentOutOfRangeException 还是让一个气泡从下面向上冒?

javascript - 如何在表单中传递隐藏值?

angular - 通过查询组件的模板获取 FormControl 实例

javascript - ionic 输入 onclick in ionic 4 angular 6