I'm trying to send a form along with a file to my API through Angular 6, but the post doesn't include the file, even though the object that's supposed to be sent does.
When I'm looking at the console logs I see what is expected, amount:"amount", invoicefile: File.... But In the outgoing request the field shows invoicefile:{}, and now file is received on the other side. Some pictures are included at the end.
Lastly my API is telling my all fields are missing, but I think that another problem.
The component looks like this:
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);
});
}
}
Followed by the service that provides the post:
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)
}
}
And lastly the class:
export class Invoice {
id: any;
serial: any;
amount: any;
debtor: any;
dateout: any;
expiration: any;
fid: any;
invoicefile: File;
}
The console log that looks correct:
And the outgoing request where the file is missing:
EDIT:
Now the service code for create looks like this:
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)
}
And the response looks like this. Looks weird to me, and I'm still getting some errors from my back-end, but that's another question.
Your POST request body is actually JSON, not Multipart as you would hope (despite what the Content-Type header says).
In order to remedy that, you need to build a FormData object, and use that in your request instead:
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)
Remove the multipart/form-data from the headers to fix this issue
const HttpUploadOptions = {
headers: new HttpHeaders({ "Content-Type": "multipart/form-data" })
}
Solution
const HttpUploadOptions = {
headers: new HttpHeaders({ "Accept": "application/json" })
}
I had previously this one which was giving error
const formData = new FormData();
formData.append(...);
this.http.post(apiUrl, {formData});
I just removed the object from braces and it worked
this.http.post(apiUrl, formData);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With