How to Upload File from Angular to ASP.NET Core Web API

前端 未结 2 956
旧时难觅i
旧时难觅i 2021-01-17 16:09

Similar questions have been asked but after looking through all of those and many blog posts on the subject I have not been able to figure this out so please forgive me.

相关标签:
2条回答
  • 2021-01-17 16:21

    my BlogController looks like this:

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

    It seems that you'd like to pass data using form-data, to achieve it, you can refer to the following code sample.

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

    Test Result

    0 讨论(0)
  • 2021-01-17 16:21

    First

    <input type="file"> binding with angular using ngModel or formControlName will only catch the value property but actually when we submit form we need the files property so we can create custom directive that will apply to all the project <input type="file"> elements so when we submit the form we got the file property

    Before

    import { Directive, forwardRef, HostListener, ElementRef, Renderer2 } from '@angular/core';
    import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
    
    
    @Directive({
        selector : `input[type=file][formControlName], 
        input[type=file][formControl],
        input[type=file][ngModel]`,
        providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: FileValueAccessorDirective,
                multi: true
            }
        ]
    })
    export class FileValueAccessorDirective implements ControlValueAccessor {
    
        constructor(private elementRef: ElementRef, private render: Renderer2) {
    
        }
    
        // Function to call when the file changes.
        onChange = (file: any) => {}
    
    
        //fire when the form value changed programmaticly
        writeValue(value: any): void {
    
        }
    
        //fire only one time to register on change event
        registerOnChange = (fn: any) => { this.onChange = fn; }
    
    
        //fire only one time to register on touched event
        registerOnTouched = (fn: any) => { }
    
    
        //Disable the input
        setDisabledState?(isDisabled: boolean): void {
    
        }
    
        //listen to change event
        @HostListener('change', ['$event.target.files'])
        handleChange(file) {
            this.onChange(file[0]);
        }
    
    }
    

    After

    Second

    To upload file using Http your data shoud be encoded using multipart/form-data that allows files to be send over http post so that why FormData is used,

    A FormData object will automatically generate request data with MIME type multipart/form-data that existing servers can process. To add a file field to the data you use a File object that an extension can construct from file path. The FormData object can then simply be passed to XMLHttpRequest:

    Http Upload Files

    so your submit method should be like

    onSubmit() {
          let formData: FormData = new FormData();
            Object.keys(this.newBlogForm.value).forEach(key => {
                formData.append(key, this.newBlogForm.value[key])
            });
        //pass formData to your service
      }
    

    Thrid

    In your postBlog method you are creating Subject without any benefit , you can just return http.post then in the caller method use specifiy whether you subscribe or use async/await to make the http call fire

    onSubmit() {
       .....
        this.postBlog(formData).subscribe(
            result => { }
        );
    }
    
    async onSubmit() {
       .....
        let res = await this.postBlog(formData).toPromise();
    }
    
    0 讨论(0)
提交回复
热议问题