Angular 6多部分表单POST请求未携带附件文件问题求助
Let's break down what's going wrong here and fix it step by step:
Core Problems
Direct Object Serialization Fails for Files
When you pass theInvoiceobject directly toHttpClient.post(), theFiletypeinvoicefilegets serialized to an empty object{}in the JSON payload. JSON doesn't natively support File objects, so this approach will never work for file uploads.Incorrect Content-Type Header for FormData
Your revised FormData approach is the right direction, but manually settingContent-Type: multipart/form-databreaks the request. Angular'sHttpClientautomatically generates the correctmultipart/form-dataheader including the boundary string when you pass aFormDataobject. If you override this header manually, the boundary is missing, and your backend can't parse the payload correctly (which explains the "all fields missing" error).
Fixed Service Code
Update your InvoiceService to remove the custom header and properly build the FormData:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Invoice } from '../_models'; @Injectable({ providedIn: 'root' }) export class InvoiceService { constructor(private http: HttpClient) { } create(invoice: Invoice){ let payload = new FormData(); // Append all form fields 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); // Append file - optionally include filename as third parameter for clarity if (invoice.invoicefile) { payload.append('invoicefile', invoice.invoicefile, invoice.invoicefile.name); } // Don't set Content-Type header manually! Let Angular handle it automatically return this.http.post('/api/v1/invoices/', payload); } }
Component Code Optimization (Optional but Recommended)
Instead of relying on the Invoice object, you can directly extract values from your registerForm to avoid potential mismatches:
deliverForm(isValid: boolean) { this.submitted = true; if (!isValid) { return; } // Extract values directly from the form group const formValues = this.registerForm.value; const payload = new FormData(); payload.append('amount', formValues.amount); payload.append('debtor', formValues.debtor); payload.append('serial', formValues.serial); payload.append('dateout', formValues.dateout); payload.append('expiration', formValues.expiration); if (this.fileToUpload) { payload.append('invoicefile', this.fileToUpload, this.fileToUpload.name); } this.invoiceService.create(payload as unknown as Invoice) .pipe(first()) .subscribe( data => { this.alertService.success('Invoice successfully uploaded', true); this.router.navigate(['/profile']); }, error => { this.alertService.error(error); }); }
Key Notes
- Always use
FormDatafor requests that include files in Angular—this is the standard way to handle multipart file uploads. - Never manually set the
multipart/form-dataheader when usingFormData—Angular handles this automatically with the correct boundary string, which is critical for backend parsing. - Double-check that your backend endpoint is configured to accept
multipart/form-datapayloads and maps the form field names (includinginvoicefile) correctly.
内容的提问来源于stack exchange,提问作者Marcus Grass

