代码之家  ›  专栏  ›  技术社区  ›  Marcus Grass

带有多部分表单的Angular 6 Post请求不包括已发布对象的附加文件

  •  7
  • Marcus Grass  · 技术社区  · 6 年前

    我试图通过Angular6将一个表单和一个文件一起发送到我的API,但是这个帖子不包含这个文件,即使应该发送的对象包含这个文件。

    当我查看控制台日志时,我看到了期望值,amount:“amount”,invoicefile:file…. 但在传出请求中,字段显示invoicefile:,现在文件在另一端接收。结尾有一些图片。

    最后,我的API告诉我所有字段都丢失了,但我认为这是另一个问题。

    组件如下所示:

    import { Component, OnInit } from '@angular/core';
    import { Router } from '@angular/router';
    import { first } from 'rxjs/operators';
    import { FormGroup, FormBuilder, FormControl, Validators, FormArray, ReactiveFormsModule } from '@angular/forms';
    import { HttpClient } from '@angular/common/http';
    
    import { AlertService } from '../_services';
    import { InvoiceService } from '../_services';
    import { Invoice } from '../_models';
    
    @Component({
      selector: 'app-registerinvoice',
      templateUrl: './registerinvoice.component.html',
      styleUrls: ['./registerinvoice.component.css']
    })
    export class RegisterinvoiceComponent implements OnInit {
      public registerForm: FormGroup;
      public submitted: boolean;
    
      constructor(
        private router: Router,
        private invoiceService: InvoiceService,
        private alertService: AlertService,
        private http: HttpClient,
    
      ) { }
      fileToUpload: File = null;
    
      ngOnInit() {
        this.registerForm = new FormGroup({
          serial: new FormControl('', [<any>Validators.required, <any>Validators.minLength(5)]),
          amount: new FormControl('', [<any>Validators.required, <any>Validators.minLength(4)]),
          debtor: new FormControl('', [<any>Validators.required, <any>Validators.minLength(10)]),
          dateout: new FormControl('', [<any>Validators.required, <any>Validators.minLength(8)]),
          expiration: new FormControl('', [<any>Validators.required, <any>Validators.minLength(8)]),
        });
      }
      handleFileInput(files: FileList){
        this.fileToUpload=files.item(0);
      }
    
      deliverForm(invoice: Invoice, isValid) {
        this.submitted=true;
        if (!isValid){
          return;
        }
        invoice.invoicefile=this.fileToUpload;
        console.log(invoice);
        console.log(typeof(invoice.invoicefile));
        this.invoiceService.create(invoice)
          .pipe(first())
          .subscribe(
            data => {
              this.alertService.success('Invoice successfully uploaded', true);
              this.router.navigate(['/profile']);
            },
            error => {
              this.alertService.error(error);
            });
      }
    
    }
    

    其次是提供岗位的服务:

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import { Http } from '@angular/http';
    import { Invoice } from '../_models';
    import { FormGroup } from '@angular/forms';
    
    const HttpUploadOptions = {
      headers: new HttpHeaders({ "Content-Type": "multipart/form-data" })
    }
    @Injectable({
      providedIn: 'root'
    })
    export class InvoiceService {
    
      constructor(
        private http: HttpClient
      ) { }
      create(invoice: Invoice){
        return this.http.post('/api/v1/invoices/', invoice, HttpUploadOptions)
      }
    }
    

    最后一个问题是:

    export class Invoice {
        id: any;
        serial: any;
        amount: any;
        debtor: any;
        dateout: any;
        expiration: any;
        fid: any;
        invoicefile: File;
    }
    

    看起来正确的控制台日志: enter image description here

    以及文件丢失的传出请求: enter image description here

    编辑:

    创建的服务代码如下:

    create(invoice: Invoice){
        let payload=new FormData();
        payload.append('amount', invoice.amount);
        payload.append('debtor', invoice.debtor);
        payload.append('serial', invoice.serial);
        payload.append('dateout', invoice.dateout);
        payload.append('expiration', invoice.expiration);
        payload.append('invoicefile', invoice.invoicefile);
        return this.http.post('/api/v1/invoices/', payload, HttpUploadOptions)
      }
    

    答案是这样的。在我看来很奇怪,我的后端仍然有一些错误,但这是另一个问题。 enter image description here

    3 回复  |  直到 6 年前
        1
  •  21
  •   user184994    6 年前

    您的post请求主体实际上是JSON,而不是您希望的多部分(尽管content-type头中说了什么)。

    为了解决这个问题,您需要构建一个FormData对象,并在您的请求中使用它:

    let input = new FormData();
    // Add your values in here
    input.append('id', invoice.id);
    input.append('invoiceFile', invoice.invoiceFile);
    // etc, etc
    
    this.http.post('/api/v1/invoices/', input, HttpUploadOptions)
    
        2
  •  11
  •   user2617449    6 年前

    从头中删除多部分/表单数据以解决此问题

    const HttpUploadOptions = {
      headers: new HttpHeaders({ "Content-Type": "multipart/form-data" })
    }
    

    解决方案

    const HttpUploadOptions = {
      headers: new HttpHeaders({ "Accept": "application/json" })
    }
    
        3
  •  2
  •   mbojko    6 年前

    我以前有过这个错误

    const formData = new FormData();
    formData.append(...);
    this.http.post(apiUrl, {formData});
    

    我刚从支架上取下物体,它就工作了

    this.http.post(apiUrl, formData);