web-dev-qa-db-fra.com

Angular 6 post-request avec un formulaire multipart n'inclut pas le fichier joint de l'objet posté

J'essaie d'envoyer un formulaire avec un fichier à mon API via Angular 6, mais la publication n'inclut pas le fichier, même si l'objet qui doit être envoyé le fait.

Lorsque je regarde les journaux de la console, je vois ce qui est attendu, montant: "montant", facturefichier: Fichier .... Mais dans la demande sortante, le champ indique facture: {}, et le fichier est maintenant reçu le l'autre côté. Certaines images sont incluses à la fin.

Enfin, mon API me dit que tous les champs sont manquants, mais je pense qu’un autre problème se pose.

Le composant ressemble à ceci:

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

}

Suivi par le service qui fournit le poste:

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)
  }
}

Et enfin la classe:

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

Le journal de la console qui semble correct:  enter image description here

Et la demande sortante où le fichier est manquant:  enter image description here

MODIFIER: 

Maintenant, le code de service pour create ressemble à ceci:

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)
  }

Et la réponse ressemble à ceci. Ça a l'air bizarre pour moi, et je continue à avoir des erreurs de mon back-end, mais c'est une autre question .  enter image description here

3
Marcus Grass

Le corps de votre demande POST est en réalité JSON et non en plusieurs parties comme vous le souhaiteriez (malgré ce que dit l'en-tête Content-Type).

Afin de remédier à cela, vous devez créer un objet FormData et l'utiliser dans votre requête:

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)
15
user184994

Supprimez les données multipart/form des en-têtes pour résoudre ce problème

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

Solution

const HttpUploadOptions = {
  headers: new HttpHeaders({ "Accept": "application/json" })
}
1
user2617449

J'avais auparavant celui qui donnait l'erreur

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

Je viens de retirer l'objet des accolades et cela a fonctionné

this.http.post(apiUrl, formData);
0
AbdulRehman