Upload image with HttpClient
Solution 1
For me the trick was not to set the content-type to multipart/form-data. But that was done automatically for me.
<label>
<input type="file" (change)="setFiles($event)" style="display:none" multiple/>
<a mat-raised-button color="primary">
<mat-icon>file_upload</mat-icon>
Select Documents
</a>
</label>
Here's my code that uploads multipart/form-data. No need to set the headers.
private setFile(event) {
let files = event.srcElement.files
if (!files) {
return
}
let path = `${environment.celoApiEndpoint}/api/patientFiles`
let data = {"patientData": {
"uid": "",
"firstName": "",
"lastName": "",
"gender": "Not Specified",
"dateOfBirth": ""
}}
// let headers = new HttpHeaders()
// .set('content-type', 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW')
// let headers = new HttpHeaders().set('content-type', 'multipart/form-data')
const formData: FormData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append(i.toString(), files[i], files[i].name);
}
formData.append("data", JSON.stringify(data));
this.http.post(path, formData).subscribe(
(r)=>{console.log('got r', r)}
)
}
Solution 2
I don't think the issue is with angular, I used the same code to send a file to the server (I am using spring in backend), the only difference is I am not observing the request or converting the response to promise.
See my code below:
let formData: FormData = new FormData();
formData.append('file', this.fileToUpload);
this.http.put(this.usersUrl, formData).subscribe(
data => {
console.log(data);
},
error => {
console.log(error);
}
);
mrkvon
Updated on June 21, 2020Comments
-
mrkvon almost 4 years
Problem
I try to upload an image with angular's
HttpClient
to APIContent-Type: multipart/form-data
(angular v4+). Is it supported? How to do it?The upload works with
XMLHttpRequest
when using module likeng2-fancy-image-uploader
. I would prefer to use a custom method withHttpClient
which i could put into a http service together with other methods for accessing API.Here is what i have tried so far:
model.service.ts
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import 'rxjs/add/operator/toPromise'; @Injectable() export class ModelService { constructor(private http: HttpClient) { } public async updateAvatar(file: File): Promise<void> { // headers const headers = new HttpHeaders() .append('Content-Type', 'multipart/form-data'); const formData: FormData = new FormData(); formData.append('avatar', file, file.name); const response: HttpResponse = await this.http .patch('https://example.com/avatar', formData, { headers, observe: 'response' }) .toPromise(); console.log(response.status); } }
avatar-uploader.component.ts
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { ModelService } from './path/to/model.service'; @Component({ selector: 'app-avatar-uploader', template: '<input type="file" #fileInput (changes)="uploadAvatar()">' }) export class AvatarUploaderComponent implements OnInit { @ViewChild('fileInput') fileInputElement: ElementRef; constructor() { } ngOnInit() { } public async uploadAvatar() { const file: File = this.fileInputElement.nativeElement.files[0]; await this.model.updateAvatar(file); } }
This version sends a request to (express) API, but
multer
(a library for parsingmultipart/form-data
requests) fails to parse the request.So i guess i either use the
HttpClient
incorrectly, or it doesn't supportmultipart/form-data
requests.I guess one could send base64 encoded file or use
XmlHttpRequest
, but i ask specifically aboutHttpClient
's ability to do it.