2

I am trying to upload different documents. But the problem comes when i choose a file 2nd time it gets added to fileArray, it don't get replaced.

For example, i have choosen a picture for 1st input. Then i decided to choose different picture for the same input then it will get added to an array of files so when i will upload it, that previous picture will also be uploaded which i don't want to.

Is there any solution (other than using multiple files upload with single button ) so that when i choose a file 2nd time then it will get replaced instead of added to the files array ?

uploadDocument.html File :

<form (ngSubmit)=f.form.valid && formSubmit() #f="ngForm">

        <input type="file" class="form-control ml-2" name="photo" ng2FileSelect [uploader]="uploader" />
          <input type="file" class="form-control ml-2" name="document1" ng2FileSelect [uploader]="uploader" />
            <input type="file" class="form-control ml-2" name="pic2" ng2FileSelect [uploader]="uploader" />

    <button type="submit" class="btn btn-danger btn-lg btn-fill">Upload</button>

</form>

uploadDocument.component.ts File :

import { Component, OnInit, Renderer, ElementRef } from '@angular/core';
import { UserService } from '../_services';
import { ActivatedRoute, Router, Params} from '@angular/router';
import { FileUploader } from 'ng2-file-upload/ng2-file-upload';
import { FileSelectDirective } from 'ng2-file-upload';

const URL = 'http://localhost:3002/api/upload';

@Component({
    selector: 'app-uploadDocument',
    templateUrl: './uploadDocument.component.html',
    styleUrls: ['./uploadDocument.component.scss']
})

export class UploadDocument implements OnInit {
    model: any = {};
    mobile: number;
    options: boolean;
    loading = false;
    public uploader:FileUploader = new FileUploader({url: URL});

    constructor(private userService: UserService, private route:ActivatedRoute,private router:Router, private el: ElementRef) { }

    ngOnInit() {


        this.uploader.onBeforeUploadItem = (item)=> {console.log("Item"); console.log(item)};

        this.uploader.onAfterAddingFile = (file)=> { file.withCredentials = false;};

       this.uploader.onCompleteItem = (item:any, response:any, status:any, headers:any) => {
             console.log("ImageUpload:uploaded:", item, status, response);
        };
    }

    formSubmit() {
        this.uploader.uploadAll();
    }

}
Farhan
  • 751
  • 1
  • 9
  • 17

3 Answers3

4

Even I lost couple of hours due to this. At last I done one tweak to fix it. Whenever a new file is uploaded, the uploaded queue is reset to store only the latest file only.This is done with the help of onAfterAddingFile callback of the library provided function. Below is the changed code.

uploadDocument.component.ts File :

import { Component, OnInit, Renderer, ElementRef } from '@angular/core';
import { UserService } from '../_services';
import { ActivatedRoute, Router, Params} from '@angular/router';
import { FileUploader, FileItem } from 'ng2-file-upload';

const URL = 'http://localhost:3002/api/upload';

@Component({
    selector: 'app-uploadDocument',
    templateUrl: './uploadDocument.component.html',
    styleUrls: ['./uploadDocument.component.scss']
})

export class UploadDocument implements OnInit {
    model: any = {};
    mobile: number;
    options: boolean;
    loading = false;
    public uploader:FileUploader = new FileUploader({url: URL});

    constructor(private userService: UserService, private route:ActivatedRoute,private router:Router, private el: ElementRef) { }

    ngOnInit() {

         this.uploader.onAfterAddingFile = (fileItem: FileItem) => this.onAfterAddingFile(fileItem)

    }

    onAfterAddingFile(fileItem: FileItem) {
       let latestFile = this.uploader.queue[this.uploader.queue.length-1]
       this.uploader.queue = []; 
       this.uploader.queue.push(latestFile);
    }

    formSubmit() {
        this.uploader.uploadAll();
    }

}

Hope this helps you!.

  • Thank you very much for your answer, i believe it will work since you have tested, i also have found out the solution before that i will post in few minutes. – Farhan Aug 02 '18 at 06:04
2

For me first three inputs were required and other three inputs were optional so i did it this way and each input will always accept only 1 file and it will get replaced if another file is choosen:

import { Component, OnInit, ElementRef } from '@angular/core';
import { ActivatedRoute, Router, Params } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { ApiDomain } from '../url.constants';

const URL = ApiDomain+'/api/upload';

@Component({
    selector: 'app-uploadDocument',
    templateUrl: './uploadDocument.component.html',
    styleUrls: ['./uploadDocument.component.scss']
})

export class UploadDocument implements OnInit {
    model: any = {};
    id: string;
    options: boolean;
    loading = false;
    files = [];
    flag: number = 0;
    formData: FormData;
    filesArray: any;

    constructor(private el: ElementRef, private route: ActivatedRoute, private router: Router, private http: HttpClient) { }

    ngOnInit() {

        this.route.params.subscribe(
            (params: Params) => {
                this.id = params["id"];
                console.log(this.id);
            });

    }

    formSubmit() {
        this.loading = true;
        let inputEl: HTMLInputElement = this.el.nativeElement.querySelector('#tenththmarksheet');
        let inputEl1: HTMLInputElement = this.el.nativeElement.querySelector('#photo');
        let inputEl2: HTMLInputElement = this.el.nativeElement.querySelector('#aadharcard');
        let inputEl3: HTMLInputElement = this.el.nativeElement.querySelector('#caste');
        let inputEl4: HTMLInputElement = this.el.nativeElement.querySelector('#bhamasha');
        let inputEl5: HTMLInputElement = this.el.nativeElement.querySelector('#moolnivas');


        let fileCount: number = inputEl.files.length;
        let fileCount1: number = inputEl1.files.length;
        let fileCount2: number = inputEl2.files.length;
        let fileCount3: number = inputEl3.files.length;
        let fileCount4: number = inputEl4.files.length;
        let fileCount5: number = inputEl5.files.length;

        let formData = new FormData();

        if (fileCount > 0 && fileCount1 > 0 && fileCount2 > 0) {

            formData.append('id', this.id);
            formData.append('tenthmarksheet', inputEl.files.item(0));
            formData.append('photo', inputEl1.files.item(0));
            formData.append('aadhar', inputEl2.files.item(0));

            if (fileCount3 > 0) {
                formData.append('castecertificate', inputEl3.files.item(0));
            }
            if (fileCount4 > 0) {
                formData.append('bhamasha', inputEl4.files.item(0));
            }

            if (fileCount5 > 0) {
                formData.append('moolniwas', inputEl5.files.item(0));
            }

            this.http.post(URL, formData).subscribe(
                (complete) => {
                    this.loading = false;    
                    this.router.navigate(['/thankyou']);
                },
                (error) => {
                    console.log(error);
                    this.loading = false;
                });
        }

    }

}
Farhan
  • 751
  • 1
  • 9
  • 17
0

Well, you can show the queue and let the user manage (delete) the files. Is not optimal but it works.

    <p class="files-uploaded" *ngFor="let item of uploader.queue">
      <strong>
        {{ item?.file?.name }} 
        <button type="button" class="btn btn-danger btn-xs"(click)="item.remove()">
          <span class="glyphicon glyphicon-trash"></span> Remove
        </button>
      </strong>
    </p>
roymckrank
  • 689
  • 3
  • 12
  • 27