使用 HttpClient 上传图片
Upload image with HttpClient
问题
我尝试将带有 angular 的 HttpClient
的图像上传到 API Content-Type: multipart/form-data
(angular v4+)。是否支持?怎么做?
当使用像 ng2-fancy-image-uploader
这样的模块时,上传与 XMLHttpRequest
一起工作。我更愿意使用带有 HttpClient
的自定义方法,我可以将它与其他访问 API.
的方法一起放入 http 服务中
这是我到目前为止尝试过的方法:
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);
}
}
头像-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);
}
}
此版本向 (express) API 发送请求,但 multer
(用于解析 multipart/form-data
请求的库)无法解析请求。
所以我想我使用 HttpClient
不正确,或者它不支持 multipart/form-data
请求。
我想可以发送 base64 编码文件或使用 XmlHttpRequest
,但我特别询问 HttpClient
的能力。
我不认为 angular 有问题,我使用相同的代码将文件发送到服务器(我在后端使用 spring),唯一的区别是我我没有观察请求或将响应转换为承诺。
查看下面我的代码:
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);
}
);
对我来说,诀窍是不要将 content-type 设置为 multipart/form-data。但这是自动为我完成的。
<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>
这是我上传的代码 multipart/form-data。无需设置 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)}
)
}
问题
我尝试将带有 angular 的 HttpClient
的图像上传到 API Content-Type: multipart/form-data
(angular v4+)。是否支持?怎么做?
当使用像 ng2-fancy-image-uploader
这样的模块时,上传与 XMLHttpRequest
一起工作。我更愿意使用带有 HttpClient
的自定义方法,我可以将它与其他访问 API.
这是我到目前为止尝试过的方法:
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);
}
}
头像-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);
}
}
此版本向 (express) API 发送请求,但 multer
(用于解析 multipart/form-data
请求的库)无法解析请求。
所以我想我使用 HttpClient
不正确,或者它不支持 multipart/form-data
请求。
我想可以发送 base64 编码文件或使用 XmlHttpRequest
,但我特别询问 HttpClient
的能力。
我不认为 angular 有问题,我使用相同的代码将文件发送到服务器(我在后端使用 spring),唯一的区别是我我没有观察请求或将响应转换为承诺。
查看下面我的代码:
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);
}
);
对我来说,诀窍是不要将 content-type 设置为 multipart/form-data。但这是自动为我完成的。
<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>
这是我上传的代码 multipart/form-data。无需设置 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)}
)
}