如何使用添加按钮在 Angular 6 中上传多个文件?

Posted

技术标签:

【中文标题】如何使用添加按钮在 Angular 6 中上传多个文件?【英文标题】:How to Upload multiple files in Angular 6 with ADDMORE button? 【发布时间】:2019-01-06 07:22:17 【问题描述】:

你好,Everone。我一直在尝试上传上面(图片)用例。我知道当我们只有一个文件时这很容易。但现在情况不同了,它由带有文件的对象数组组成。 现在我的问题是如何使用对象数组呈现 formdata 对象,其中每个对象都由一个文件组成。对于动态形式,我使用了角度反应形式。任何人都可以请建议我如何通过单击保存按钮将整个数据发送到支持。 对于后端,我使用了 Springmvc。 提前致谢。

我的 Github 上有完整的源代码:Source

多文件上传.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>

多文件上传.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);

  


上传控制器.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 我没有将任何文件发送到我的后端,所以我假设我的 component.ts 中的 formdata 的呈现可能是一个问题。所以我想知道如何在何时呈现 formdata 对象这种场景。 不要在标题中加上“SOLVED”,只要接受你的答案,就意味着它正在被解决。 【参考方案1】:

在尝试了不同的场景来渲染 formdata 对象后,我在一个场景中成功了。

GitHub 链接:Source

更新文件

多文件上传.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>

多文件上传.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 ";
        

如果您不理解代码,请将其 fork 到您的存储库,然后使用控制台日志进行克隆和调试,这样您就可以清楚地理解代码。谢谢

【讨论】:

以上是关于如何使用添加按钮在 Angular 6 中上传多个文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PHP、jQuery 和 AJAX 上传多个文件

如何在 Angular 6 中上传之前验证文件

如何在 Angular 中使用多个 ViewChild 元素 (2/4)

Angular 6 Datatables为按钮添加点击事件

如何使用Angular 5在单击按钮时调用多个方法?

单击添加按钮时,角度选择多个文件而不上传和上传