简体   繁体   English

在 Angular 5 中使用文件上传保存 FormData

[英]Save FormData with File Upload in Angular 5

I am trying to save files along with FormData in Angular 5. I can get the single file, but have no idea how to get all the files uploaded.我正在尝试将文件与 Angular 5 中的 FormData 一起保存。我可以获得单个文件,但不知道如何上传所有文件。 I have three image files and input fields, tried searching examples.我有三个图像文件和输入字段,尝试搜索示例。 But only got for multiple file uploads.但仅适用于多个文件上传。 I want to upload each and every single file from this form.我想从这个表单上传每一个文件。

Below is my code :下面是我的代码:

 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>

I recently had a similar issue.我最近有一个类似的问题。 This can be solved by setting the content type of header as null in the Angular code.这可以通过在 Angular 代码中将 header 的内容类型设置为 null 来解决。 Attaching the code snippet of Angular5 and spring boot backend.附上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
        }

Here's how I handle multiple files from a single file input.以下是我如何处理来自单个文件输入的多个文件。 My component gathers the form data, and produces a Data object, which does not contain the files.我的组件收集表单数据,并生成一个不包含文件的 Data 对象。 It then calls this service method with the Data object and the files, which sends the data and the files in a multipart post.然后,它使用 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);
  }

So, to handle two file inputs, you could do this:因此,要处理两个文件输入,您可以这样做:

 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);
  }

Which would give you three parts in your multipart post, one for each set of files, and one for the data object.这将在您的多部分帖子中为您提供三个部分,一个用于每组文件,一个用于数据对象。

This is what I tried and it worked as expected :这是我尝试过的,它按预期工作:

 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>

just put 'multiple' attribute on your input tag now by selecting 2 or more files on browsing you will get object should iterate on it to extract images on it.现在只需在您的输入标签上放置“多个”属性,通过在浏览时选择 2 个或更多文件,您将获得对象应该对其进行迭代以提取图像。 like this-->像这样-->

 <div class="form-group">
    <label for="file">Choose File</label>
    <input type="file" id="file" (change)="handleFileInput($event.target.files)" multiple>
</div>

Try this code:试试这个代码:

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);
    }
}

Was having same trouble the below code worked for me遇到同样的问题,下面的代码对我有用

postFile(apiPath: string, data:any){
    this.http.post<any>(apiPath, data).subscribe(
      (res) => console.log(res),
      (err) => console.log(err)
    );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM