Download files with angular2 - ionic 2

2019-02-25 09:37发布

I have an Ionic 2 app, and I need to download audios from soundcloud. I already have the url that I need to do the request:

let url = `https://api.soundcloud.com/tracks/${audio.id}/download?client_id=${this.SC_CLIENT_ID}`

I want to know how to do this. I tryed with FileTransfer:

public download(audio: any): void {

        this.platform.ready().then(() => {
            console.log("Clickeo para descargar: " + audio.id);

            let url = `https://api.soundcloud.com/tracks/${audio.id}/download?client_id=${this.SC_CLIENT_ID}`;

            let pathToSaveTo: string = '';

            if (this.platform.is('android')) {
                pathToSaveTo = cordova.file.externalApplicationStorageDirectory + audio.id + '.wav';

                let fileTransfer = new Transfer();

                fileTransfer.onProgress(this.onProgress);

                fileTransfer.download(url, pathToSaveTo)
                    .then((entry) => {
                        console.log('download complete: ' + entry.toURL());
                    }, (error) => {

                        let prompt = this.alertCtrl.create({
                            title: 'Error',
                            subTitle: error,
                            buttons: ['Accept']
                        });

                        prompt.present();
                    });
            }
        });

    }

    onProgress = (progressEvent: ProgressEvent) : void => {
        this.ngZone.run(() => {
            if (progressEvent.lengthComputable) {
                let progress: any = Math.round((progressEvent.loaded / progressEvent.total) * 100);
                console.log(progress);
                let toast = this.toastCtrl.create({
                  message: progress,
                  duration: 100
                });
                toast.present();
            }
        });
    }

But it always download a zero KB file. Any solution? Maybe angular2 way, or I'm doing it wrong? If I put this url in browser, with the properly audio id and mi client id, it starts to download, but not with FileTransfer.

Thank's so much in advance.

Ivan.

1条回答
Fickle 薄情
2楼-- · 2019-02-25 10:11

My problem was that soundcloud returned a response with redirect. I had to detect the redirect state and manually redirect to the response.headers.Location

That is the working code:

public download(localAudio: LocalAudio): void {
    let fileName: string = localAudio.id + '.mp3';

    var audio: StorageAudio = {
        localAudio: localAudio,
        url: `https://api.soundcloud.com/tracks/${localAudio.id}/download?client_id=${this.SC_CLIENT_ID}`,
        fileName: fileName,
        filePath: this.file.dataDirectory + fileName
    };

    if (this.platform.is('ios')) {
        audio.filePath = audio.filePath.replace(/^file:\/\//, '');
    }

    this.toastNotifications.showStartingDownloadMsg();

    this.http.downloadFile(audio.url, {}, {}, audio.filePath).then(response => {
        this.toastNotifications.showDownloadCompleteMsg();

        this.storeAudioInformation(audio);
    }).catch(response => {
        /**
         * Handle redirects if exist.
         */
        if (this.hasRedirection(response)) {
            console.log("Redirect to " + response.headers.Location);
            audio.url = response.headers.Location;

            this.redirectToDownload(audio);
        } else {
            this.toastNotifications.showDownloadErrorMsg();
        }
    });
}

public hasRedirection(response: any): boolean {
    return (response.headers.Location && (response.status === 301 || response.status === 302));
}

public redirectToDownload(audio: StorageAudio): void {
    this.http.downloadFile(audio.url, {}, {}, audio.filePath).then(response => {
        this.toastNotifications.showDownloadCompleteMsg();

        this.storeAudioInformation(audio);
    }).catch(response => {
        console.log("Error catch: " + JSON.stringify(response));
    });
}
查看更多
登录 后发表回答