How to Upload multiple files in Angular 6 with ADDMORE button?

16,518

After trying with different scenarios to rendering the formdata object, I succeed in one scenario.

GitHub Link: Source

Updated files

multi-files-upload.component.html

<div class="container-fluid">

  <section class="content">

    <div id="main-form-content">
      <form [formGroup]="documentGrp" (ngSubmit)="OnSubmit(documentGrp.value)" #uploadDocumentsForm="ngForm" ngNativeValidate>



        <div class="box box-solid box-primary">

          <div class="box-body" formArrayName="items">


            <h2 class="page-header  text-blue ">
              <i class="fa fa-files-o"></i> Upload Documents
            </h2>
            <div class="row">
              <div class="col-sm-12">


                <div *ngFor="let item of items.controls; let i = index;">
                  <div [formGroupName]="i">
                    <table id="tbl-upload" class="table table-bordered">
                      <tbody>
                        <tr *ngIf="i==0" class="active">
                          <th>Document Name</th>
                          <th>Document Description</th>
                          <th>Document File</th>
                          <th>&nbsp;</th>
                        </tr>
                        <tr>
                          <td>
                            <div class="form-group required">
                              <input type="text" class="form-control" name="doc_name" formControlName="doc_name" placeholder="Enter document Category"
                                required="">




                              <div class="help-block"></div>
                            </div>
                          </td>

                          <td>
                            <div class="form-group ">

                              <input type="text" class="form-control" name="doc_description" formControlName="doc_description" maxlength="100" placeholder="Enter document related descriptions"
                                required="">

                              <div class="help-block"></div>
                            </div>
                          </td>
                          <td>
                            <div class="form-group  required">

                              <input type="file" title="Browse Document"   (change)="fileSelectionEvent($event,i)" required="">
                              <div class="help-block"></div>
                            </div>
                          </td>
                          <td class="remove" *ngIf=" i!=0 ">
                            <a title="Remove" (click)="removeItem(i)" class="fa fa-minus-square fa-lg text-red"></a>
                          </td>
                        </tr>
                      </tbody>
                    </table>
                  </div>
                </div>
                <div class="pull-right">
                  <button type="submit" class="btn btn-sm btn-success" title="Add More" style="" (click)="addItem()">Add More</button>

                </div>
              </div>
              <!--./col-->
            </div>
            <!--./row-->
          </div>
          <!--./box-body-->
          <div class="box-footer" style="align-content: center">
            <button type="submit" class="btn btn-primary pull-right">Save</button>
          </div>
        </div>
      </form>
    </div>


  </section>
</div>

multi-files-upload.component.ts

import { Component, OnInit, Renderer, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormArray, FormControl, NgForm } from '@angular/forms';
import { MultifilesService } from './multifiles.service'
@Component({
  selector: 'app-multi-files-upload',
  templateUrl: './multi-files-upload.component.html',
  styleUrls: ['./multi-files-upload.component.css']
})
export class MultiFilesUploadComponent implements OnInit {

  constructor(private renderer: Renderer,
    private formBuilder: FormBuilder,
    private multifilesService: MultifilesService
  ) { }

  public documentGrp: FormGroup;
  public totalfiles: Array<File> =[];
  public totalFileName = [];
  public lengthCheckToaddMore =0;

  ngOnInit() {

    this.documentGrp = this.formBuilder.group({
      doc_name: '',
      doc_description: '',
      documentFile:new FormControl(File),

      items: this.formBuilder.array([this.createUploadDocuments()])
    });

  }
  createUploadDocuments(): FormGroup {
    return this.formBuilder.group({
      doc_name: '',
      doc_description: '',
      documentFile : File
    });
  }

  get items(): FormArray {
    return this.documentGrp.get('items') as FormArray;
  };

  addItem(): void {


//console.log("length is ",this.totalfiles.length);
//console.log("lengthCheckToaddMore ", this.lengthCheckToaddMore);

if(this.totalfiles.length!=0)
if( this.items.value[0].doc_name != "" && this.items.value[0].doc_description != "" && ((this.lengthCheckToaddMore) === (this.totalfiles.length)) )
{

    this.items.insert(0, this.createUploadDocuments())
     this.lengthCheckToaddMore=this.lengthCheckToaddMore+1;
}
  }

  removeItem(index: number) {

   this.totalfiles.splice(index);
   this.totalFileName.splice(index);
    this.items.removeAt(index);
    this.lengthCheckToaddMore=this.lengthCheckToaddMore-1;
   // console.log("name are ",this.totalFileName);

  }

  public fileSelectionEvent(fileInput: any,oldIndex) {

    //console.log("oldIndex is ", oldIndex);

    if (fileInput.target.files && fileInput.target.files[0]) {
      var reader = new FileReader();
      reader.onload = (event: any) => {
      }
      if(oldIndex==0)
    {
      this.totalfiles.unshift((fileInput.target.files[0]))
      this.totalFileName.unshift(fileInput.target.files[0].name)
    }
    else
    {
      this.totalfiles[oldIndex]=(fileInput.target.files[0]);
      this.totalFileName[oldIndex]=fileInput.target.files[0].name
    }

      reader.readAsDataURL(fileInput.target.files[0]);
    }

    if(this.totalfiles.length == 1)
    {
      this.lengthCheckToaddMore=1;
    }

  }




  public OnSubmit(formValue: any) {


    let main_form: FormData = new FormData();

    for(let j=0;j<this.totalfiles.length; j++)
    {
      console.log("the values is ",<File>this.totalfiles[j]);
      console.log("the name is ",this.totalFileName[j]);

      main_form.append(this.totalFileName[j],<File>this.totalfiles[j])
    }
    console.log(formValue.items)



    //reverseFileNames=this.totalFileName.reverse();

    let AllFilesObj= []

    formValue.items.forEach((element, index) => { 

      console.log("index is ",index);
      console.log("element is ", element);

      let eachObj=
      {
        'doc_name' : element.doc_name,
        'doc_description' : element.doc_description,
        'file_name' : this.totalFileName[index]
      }
      AllFilesObj.push(eachObj); 
    });

    //console.log("the Array data is ",AllFilesObj);
    main_form.append("fileInfo",JSON.stringify(AllFilesObj))

    this.multifilesService.saveFiles(main_form).subscribe(data => {
      //console.log("result is ", data)
    })
  }



}

Multifiles.service.ts

same code already in the question section.

MultiFileController.java

@PostMapping("uploadFiles")
        public String uploadMultiFiles(HttpServletRequest request) 
        {
            System.out.println("hitting uploadFiles");
            //System.out.println("data is "+ upladeedFiles);


            List documentList= new ArrayList<>();


            //System.out.println(request.getParameter("fileInfo"));

            JSONArray jsonArray = new JSONArray(request.getParameter("fileInfo"));

             for (int i = 0; i < jsonArray.length(); i++)
                {
                    JSONObject jsonObj = jsonArray.getJSONObject(i);
                    documentList.add(jsonObj);

                    System.out.println("index "+ i +" --  "+jsonObj);
                }




            MultipartHttpServletRequest multiPartRequest = new DefaultMultipartHttpServletRequest(request);

            try {

                multiPartRequest = (MultipartHttpServletRequest) request;
                multiPartRequest.getParameterMap();

                Iterator<String> itr = multiPartRequest.getFileNames();
                while (itr.hasNext()) {

                    MultipartFile mFile = multiPartRequest.getFile(itr.next());


                    System.out.println("FileName is "+mFile.getOriginalFilename());

                    // Do something with the mfile based on your requirement



                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            return "uploaded ";
        }

If you don't understand the code please fork it to your repository then clone and debug with console logs then you can clearly understand the code. Thanks

Share:
16,518
SHIVA
Author by

SHIVA

Updated on August 02, 2022

Comments

  • SHIVA
    SHIVA over 1 year

    Hello, Everone. I've been trying to Upload above(image) use case. I know it is very easy when we have a single file. but now the scenario is different it consists of an array of objects with the file. Now my question is how can I render the formdata object with the array of objects where each object consists of a file. For dynamic form, I used angular reactive forms. Can anyone please suggest me how can send whole data to the backed with the single click on save button. For backend I used Springmvc. Thanks in advance.

    FullSource code availabe on my Github : Source

    multi-files-upload.component.html

    <div class="container-fluid">
    
      <section class="content">
    
        <div id="main-form-content">
          <form [formGroup]="documentGrp" (ngSubmit)="OnSubmit(documentGrp.value)" #uploadDocumentsForm="ngForm" ngNativeValidate>
    
    
    
            <div class="box box-solid box-primary">
    
              <div class="box-body" formArrayName="items">
    
    
                <h2 class="page-header  text-blue ">
                  <i class="fa fa-files-o"></i> Upload Documents
                </h2>
                <div class="row">
                  <div class="col-sm-12">
    
    
                    <div *ngFor="let item of items.controls; let i = index;">
                      <div [formGroupName]="i">
                        <table id="tbl-upload" class="table table-bordered">
                          <tbody>
                            <tr *ngIf="i==0" class="active">
                              <th>Document Name</th>
                              <th>Document Description</th>
                              <th>Document File</th>
                              <th>&nbsp;</th>
                            </tr>
                            <tr>
                              <td>
                                <div class="form-group required">
                                  <input type="text" class="form-control" name="doc_name" formControlName="doc_name" placeholder="Enter document Category"
                                    required="">
    
    
    
    
                                  <div class="help-block"></div>
                                </div>
                              </td>
    
                              <td>
                                <div class="form-group ">
    
                                  <input type="text" class="form-control" name="doc_description" formControlName="doc_description" maxlength="100" placeholder="Enter document related descriptions"
                                    required="">
    
                                  <div class="help-block"></div>
                                </div>
                              </td>
                              <td>
                                <div class="form-group  required">
    
                                  <input type="file" name="admission_docs_path" title="Browse Document" (change)="fileSelectionEvent($event)" required="">
                                  <div class="help-block"></div>
                                </div>
                              </td>
                              <td class="remove" *ngIf=" i!=0 ">
                                <a title="Remove" (click)="removeItem(i)" class="fa fa-minus-square fa-lg text-red"></a>
                              </td>
                            </tr>
                          </tbody>
                        </table>
                      </div>
                    </div>
                    <div class="pull-right">
                      <a class="btn btn-sm btn-success" title="Add More" style="" (click)="addItem()">
                        <i class="fa fa-plus-square"></i>&nbsp; Add More</a>
                    </div>
                  </div>
                  <!--./col-->
                </div>
                <!--./row-->
              </div>
              <!--./box-body-->
              <div class="box-footer" style="align-content: center">
                <button type="submit" class="btn btn-primary pull-right">Save</button>
              </div>
            </div>
          </form>
        </div>
    
    
      </section>
    </div>
    

    multi-files-upload.component.ts

    import { Component, OnInit, Renderer } from '@angular/core';
    import { FormBuilder, FormGroup, Validators, FormArray, FormControl, NgForm } from '@angular/forms';
    import { MultifilesService } from './multifiles.service'
    @Component({
      selector: 'app-multi-files-upload',
      templateUrl: './multi-files-upload.component.html',
      styleUrls: ['./multi-files-upload.component.css']
    })
    export class MultiFilesUploadComponent implements OnInit {
    
      constructor(private renderer: Renderer,
        private formBuilder: FormBuilder,
        private multifilesService: MultifilesService
      ) { }
      public documentGrp: FormGroup;
    
      ngOnInit() {
    
        this.documentGrp = this.formBuilder.group({
          doc_name: '',
          doc_description: '',
          documentFile: File,
    
          items: this.formBuilder.array([this.createUploadDocuments()])
        });
    
      }
    
    
      public doc_name = "";
      public doc_description = "";
      public documentFile: File;
    
    
    
      createUploadDocuments(): FormGroup {
        return this.formBuilder.group({
          doc_name: '',
          doc_description: '',
          documentFile: File,
        });
      }
    
      get items(): FormArray {
        return this.documentGrp.get('items') as FormArray;
      };
    
      addItem(): void {
        this.items.insert(0, this.createUploadDocuments())
      }
    
      removeItem(index: number) {
        this.items.removeAt(index);
      }
      public fileSelectionEvent(fileInput: any) {
        if (fileInput.target.files && fileInput.target.files[0]) {
          var reader = new FileReader();
          reader.onload = (event: any) => {
          }
    
          this.documentFile = (fileInput.target.files[0]);
    
    
    
          console.log("the document  is" + JSON.stringify(fileInput.target.files[0].name));
          reader.readAsDataURL(fileInput.target.files[0]);
        }
      }
    
    
    
    
      public OnSubmit(formValue: any) {
        let total_form: FormData[] = [];
    
        console.log(formValue.items)
    
        formValue.items.forEach(element => {
          let upl_fom: FormData = new FormData();
          console.log("each element is", element);
          upl_fom.append('document_category', element.doc_name);
          upl_fom.append('document_details', element.doc_description);
          upl_fom.append('document_file', element.documentFile);
          total_form.push(upl_fom);
        });
    
        this.multifilesService.saveFiles(total_form).subscribe(data => {
          console.log("result is ", data)
        })
      }
    
    
    
    }
    

    Multifiles.service.ts

    import { Injectable } from '@angular/core';
    import { HttpClient,HttpHeaders } from '@angular/common/http';
    @Injectable({
      providedIn: 'root'
    })
    export class MultifilesService {
    
      constructor(  private http: HttpClient) { }
    
      saveFiles(total_form)
      {
    
        return this.http.post("http://localhost:8181/uploadFiles",total_form);
    
      }
    
    }
    

    UploadController.java

            @PostMapping("uploadFiles")
            public String uploadMultiFiles(HttpServletRequest request)
            {
                System.out.println("hitting uploadFiles");
                Enumeration e =request.getParameterNames();
                while(e.hasMoreElements())
                {
                    System.out.println(e.nextElement());
                }
    
    
                MultipartHttpServletRequest multiPartRequest = new DefaultMultipartHttpServletRequest(request);
                try {
                    multiPartRequest = (MultipartHttpServletRequest) request;
                    multiPartRequest.getParameterMap();
                    //multipartRequest.
                    Iterator < String > it = multiPartRequest.getFileNames();
    
                    int i = 1;
    
                    while (it.hasNext()) {
                        MultipartFile multipart = multiPartRequest.getFile(it.next());
                        System.out.println("File name is "+multipart.getOriginalFilename());
                    }
                }catch(Exception ex) {
    
    
                }
                return "uploaded ";
            }
    
    • Chellappan வ
      Chellappan வ almost 6 years
      what is the issue now?
    • SHIVA
      SHIVA almost 6 years
      @Chellappan I didn't get any files to my backend so i am assuming the rendering of formdata in my component.ts may be an issue.so I want to know how to render the formdata object when this type of scenario.
    • Joseph Webber
      Joseph Webber almost 6 years
      Don't add "SOLVED" to the title, just accept your answer and it being solved will be implied.