mostrar - subir imagen angular 4
Subir imagen con HttpClient (2)
Problema
Intento subir una imagen con HttpClient
a API Content-Type: multipart/form-data
angular Content-Type: multipart/form-data
(angular v4 +). ¿Es compatible? ¿Cómo hacerlo?
La carga funciona con XMLHttpRequest
cuando se usa un módulo como ng2-fancy-image-uploader
. Preferiría usar un método personalizado con HttpClient
que podría poner en un servicio http junto con otros métodos para acceder a la API.
Esto es lo que he intentado hasta ahora:
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);
}
}
Esta versión envía una solicitud a (expreso) API, pero multer
(una biblioteca para analizar solicitudes multipart/form-data
) no puede analizar la solicitud.
Así que supongo que o bien uso incorrectamente el HttpClient
, o no es compatible multipart/form-data
solicitudes de multipart/form-data
.
Supongo que uno podría enviar un archivo codificado en base64 o utilizar XmlHttpRequest
, pero le pregunto específicamente sobre la capacidad de HttpClient
para hacerlo.
No creo que el problema sea angular, utilicé el mismo código para enviar un archivo al servidor (estoy usando Spring en el backend), la única diferencia es que no estoy observando la solicitud o convirtiendo la respuesta en una promesa.
ver mi código a continuación
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);
}
);
Para mí, el truco no era establecer el tipo de contenido en multipart / form-data. Pero eso se hizo automáticamente por mí.
<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>
Aquí está mi código que carga multipart / form-data. No es necesario configurar los encabezados.
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)}
)
}