2

I have Angular 2 client that download a file from rest service:

 downloadAPK(projectName: string): void {
    this.projectService.downloadAppFile(projectName).subscribe(blobContent => {
        var a = document.createElement("a");
        a.setAttribute('style', 'display:none;');
        document.body.appendChild(a);
        var url = window.URL.createObjectURL(blobContent);
        a.href = url;
        a.download = projectName + '.apk';
        a.click();
    });

}

The Client code:

<div class="subTitleStatus">Ready 
    <a style="cursor:pointer" (click)="downloadAPK(project.name)"><i class="glyphicon glyphicon-download-alt"></i></a>
</div>

The Service code:

downloadAppFile(projectName: String): any {
    return this._http.get(this._productUrl + "/downloadAppFile/" + projectName,
        {responseType: ResponseContentType.Blob})
        .map(res => res.blob())
        .catch(this.handleError);
}

The problem is that the user does not have any indication that the download started until the client finish downloading the file. i'm talking about huge files

how can i change the client code to show downloading percentage when the user click the download link until finish downloading?

Thanks

Claies
  • 22,124
  • 4
  • 53
  • 77
Yosefarr
  • 709
  • 5
  • 12
  • 26

1 Answers1

4

why are you not downloading the file with as a link?

First solution(Download link):

you don't need to download via service, just load the link in a new tab and browser will download it (if you have the correct headers like attachment header from the server)

    <div class="subTitleStatus">Ready 
        <a style="cursor:pointer" [attr.href]="downloadAPK(project.name)" target="_blank">
            <i class="glyphicon glyphicon-download-alt"></i>
        </a>
    </div>

and this the service

    downloadAppFile(projectName: String): any {
        return this._productUrl + "/downloadAppFile/" + projectName;
    }

Second solution(Via JavaScript): you have another solution, but need some changes in server side please read How to get progress from XMLHttpRequest and more specific to angular2 Angular 2 HTTP Progress bar

Third Solution(Via Javascript - indeterminate):

downloadAppFile(projectName: String, start: ()=>void, stop: ()=>void): any {
    return this._http.get(this._productUrl + "/downloadAppFile/" + projectName,
        {responseType: ResponseContentType.Blob})
        .do(start)
        .map(res => res.blob())
        .finally(stop)
        .catch(this.handleError);
}

and in your controller define stop and start

start can be something like:

() => { this.showSpinner = true }

and stop:

() => { this.showSpinner = false }

so the final controller is something like:

downloadAPK(projectName: string): void {
    showSpinner = false;
    start = () => { this.showSpinner = true }
    stop = () => { this.showSpinner = false }
    this.projectService.downloadAppFile(projectName, this.start, this.stop).subscribe(blobContent => {
        var a = document.createElement("a");
        a.setAttribute('style', 'display:none;');
        document.body.appendChild(a);
        var url = window.URL.createObjectURL(blobContent);
        a.href = url;
        a.download = projectName + '.apk';
        a.click();
    });

}

and in view just add a spinner and show/hide it based on this.showSpinner variable

if you don't send the file size from the server you cannot determine the downloaded percentage

Updates

the third solution added

the first solution is updated based on Angular2 set href in attribute directive

in first solution there was a type and href changed to [attr.href]

Community
  • 1
  • 1
Mahmood Sajjadi
  • 422
  • 5
  • 12
  • I prefer not to change the server side, href="downloadAPK(project.name)" does not work in Angular 2 – Yosefarr Apr 24 '17 at 04:55
  • what about the second solution, if the second one is not good for you because of server side changes, the only solution remains is indeterminate progress/spinner you can start in "do" section of Observable HTTP call and stop it on compleated/finally section – Mahmood Sajjadi Apr 24 '17 at 05:20