Angular 5.でFormDataと共にファイルを保存しようとしています。5つのファイルを取得できますが、すべてのファイルをアップロードする方法がわかりません。3つの画像ファイルと入力フィールドがあります。例を検索してみましたが、複数のファイルのアップロードしかできませんでした。このフォームからすべてのファイルをアップロードしたいと思います。
以下は私のコードです:
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Location } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { Category } from '../../../shared/services/categories/category';
import { CategoriesService } from '../../../shared/services/categories/categories.service';
@Component({
selector: 'app-add-category',
templateUrl: './add-category.component.html',
styleUrls: ['./add-category.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class AddCategoryComponent implements OnInit {
category: Category = new Category();
fileToUpload: File = null;
constructor(
private categoriesService: CategoriesService,
private route: ActivatedRoute,
private location: Location
) { }
ngOnInit() {
}
goBack(): void {
this.location.back();
}
handleFileInput(files: FileList) {
console.log(files);
}
addCategory() {
console.log(this.category);
this.categoriesService.createCategory(this.category).subscribe(() => this.goBack());
}
}
<h3 class="box-title">Category</h3>
<form role="form" (ngSubmit)="addCategory()" #categoryForm="ngForm">
<div class="box-body">
<div class="row">
<div class="col-lg-6">
<label for="Category Name">Name</label>
<input type="text" class="form-control" [(ngModel)]="category.category_name" name="category_name" id="category_name" placeholder="Enter Category Name" required="">
</div>
<div class="col-lg-6">
<label for="Category Path">Path</label>
<input type="text" class="form-control" [(ngModel)]="category.category_path" name="category_path" id="category_path" required="">
</div>
</div>
</div>
<br/>
<div class="form-group">
<label for="Category Description">Description</label>
<textarea rows="3" [(ngModel)]="category.category_description" name="category_description" id="category_description" class="form-control" required=""></textarea>
</div>
<div class="col-lg-12 text-center">
<input type="file" [(ngModel)]="category.category_banner" (change)="handleFileInput($event.target.files)" class="custom-file-input" name="category_banner" id="category_banner">
<label class="custom-file-label" for="customFile">Banner</label>
</div>
<br/>
<div class="form-group">
<label for="Category Banner Code">Banner Code</label>
<textarea rows="3" [(ngModel)]="category.category_banner_code" name="category_banner_code" id="category_banner_code" class="form-control" required=""></textarea>
</div>
<br/>
<div class="col-lg-12">
<input type="file" [(ngModel)]="category.category_image" (change)="handleFileInput($event.target.files)" class="custom-file-input" name="category_image" id="category_image">
<label class="custom-file-label" for="customFile">Image</label>
</div>
<br/>
<div class="col-lg-12">
<input type="file" [(ngModel)]="category.category_icon" (change)="handleFileInput($event.target.files)" class="custom-file-input" name="category_icon" id="category_icon">
<label class="custom-file-label" for="customFile">Icon</label>
</div>
<div class="form-group">
<label for="Category Meta Title">Meta Title</label>
<input type="text" [(ngModel)]="category.category_meta_title" class="form-control" name="category_meta_title" id="category_meta_title" placeholder="Enter Meta Title" required="">
</div>
<div class="form-group">
<label for="Category Meta Description">Meta Description</label>
<input type="text" [(ngModel)]="category.category_meta_decription" class="form-control" id="category_meta_description" name="category_meta_description" placeholder="Enter Meta Description" required="">
</div>
<div class="form-group">
<label for="Category Meta Keyword">Meta Keyword</label>
<input type="text" [(ngModel)]="category.category_meta_keyword" class="form-control" id="category_meta_keyword" name="category_meta_keyword" placeholder="Enter Meta Keyword" required="">
</div>
<div class="form-group">
<div class="row">
<div class="col">Featured :</div>
<div class="col">
<label class="radio-inline" for="Category Featured">
<input type="radio" [(ngModel)]="category.category_featured" name="category_featured" id="category_featured" value="1" required="">Yes
</label>
</div>
<div class="col">
<label class="radio-inline" for="Category Featured">
<input type="radio" [(ngModel)]="category.category_featured" name="category_featured" id="category_featured" value="0" required="">No
</label>
</div>
</div>
</div>
<input type="hidden" [(ngModel)]="category.category_status" name="category_status" id="category_status" value="1">
<div class="box-footer col-md-12">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
これは私が試したものであり、期待どおりに機能しました:
handleCategoryBanner(files: FileList) {
this.category.category_banner = '/categories/download/' + files[0].name;
this.formData.append('category_banner', files[0], files[0].name);
this.categoryContainersService.uploadFile(this.formData).subscribe(filename => console.log(files[0].name));
}
<div class="col-lg-12 text-center">
<input type="file" (change)="handleCategoryBanner($event.target.files)" class="custom-file-input" id="category_banner" accept=".jpeg,.png,.jpg">
<input type="hidden" name="category_banner" [(ngModel)]="category.category_banner" />
<label class="custom-file-label" for="customFile">Banner</label>
</div>
最近、同様の問題が発生しました。これは、Angularコードでヘッダーのコンテンツタイプをnullに設定することで解決できます。Angular5のコードスニペットとSpring Bootバックエンドを添付します。
let headers = new HttpHeaders();
//this is the important step. You need to set content type as null
headers.set('Content-Type', null);
headers.set('Accept', "multipart/form-data");
let params = new HttpParams();
const formData: FormData = new FormData();
for (let i = 0; i < this.filesList.length; i++) {
formData.append('fileArray', this.filesList[i], this.filesList[i].name);
}
formData.append('param1', this.param1);
formData.append('param2', this.param2);
this.http.post(this.ROOT_URL + this.SERVICE_ENDPOINT, formData, { params, headers }).subscribe((res) => {
console.log(res);
});
In the spring boot backend, you need to have the controller as -
@RequestMapping(value = "/uploadAndSendEmail", method = RequestMethod.POST, consumes= "multipart/form-data")
public ResponseEntity<String> uploadAndSendEmail(@RequestParam("fileArray") MultipartFile[] fileArray,
@RequestParam(value = "param1", required = false) String param1,
@RequestParam(value = "param2", required = false) String param2) {
//do your logic
}
ブラウジング時に2つ以上のファイルを選択して、入力タグに 'multiple'属性を配置するだけで、オブジェクトを反復処理して画像を抽出できます。このように->
<div class="form-group">
<label for="file">Choose File</label>
<input type="file" id="file" (change)="handleFileInput($event.target.files)" multiple>
</div>
このコードを試してください:
handleFileInput(files){
for (let j = 0; j < files.length; j++) {
let data = new FormData();
let fileItem = files[j]._file;
console.log(fileItem.name);
data.append('file', fileItem);
}
}
これが、単一のファイル入力から複数のファイルを処理する方法です。私のコンポーネントはフォームデータを収集し、ファイルを含まないDataオブジェクトを生成します。次に、Dataオブジェクトとファイルを使用してこのサービスメソッドを呼び出し、データとファイルをマルチパートポストで送信します。
save(data: Data, filesForUpload: File[]): Observable<Data> {
const formData = new FormData();
// add the files
if (filesForUpload && filesForUpload.length) {
filesForUpload.forEach(file => formData.append('files', file));
}
// add the data object
formData.append('data', new Blob([JSON.stringify(data)], {type: 'application/json'}));
return this.http.post<Data>(this.apiUrl, formData);
}
したがって、2つのファイル入力を処理するには、次のようにします。
save(data: Data, filesA: File[], filesB: File[]): Observable<Data> {
const formData = new FormData();
// add the files
if (filesA && filesA.length) {
filesA.forEach(file => formData.append('filesA', file));
}
if (filesB && filesB.length) {
filesB.forEach(file => formData.append('filesB', file));
}
// add the data object
formData.append('data', new Blob([JSON.stringify(data)], {type: 'application/json'}));
return this.http.post<Data>(this.apiUrl, formData);
}
これにより、マルチパート投稿に3つのパートが提供されます。1つはファイルのセットごと、もう1つはデータオブジェクト用です。