NativeScript + Angular 2 - Download and Open file on iOS

While there is a ton of love about the {N}+ng combo, there seem to be some rough edges as well. This isn't entirely unexpected, as it's a relatively new mobile stack, and one with huge potential.

While trying to use Angular's Http.post(...), I continued to run into problems using the Response.arrayBuffer() or Response.blob() methods to create a file that NativeScript was able to save/open successfully. So I decided to switch to NativeScript's http.getFile() method. That, combined with NativeScript's iOS-specific utils.ios.openFile() method, I was able to easily download, save, and open binary files from a backend.

Full example app

{N}+ng Component (app.component.ts)

import {Component} from "@angular/core";  
import * as http from "http";  
import * as fs from "file-system";  
import * as utilModule from "utils/utils";

@Component({
    selector: "my-app",
    templateUrl: "app.component.html",
})
export class AppComponent {  
    public downloadAndOpenPDF(): void {
        let filename: string = 'test.pdf';
        let url: string = `https://blog.zgoda.us/content/images/2017/01/${filename}`;
        let path: string = fs.path.join(fs.knownFolders.documents().path, filename);

        http.getFile({
            url: url,
            method: "GET"
        }, path)
            .then(file => {
                console.log(`Downloaded File: ${JSON.stringify(file)}`);
                if (file && fs.File.exists(file.path)) {
                    let opened = utilModule.ios.openFile(file.path);
                    console.log(opened ? 'Opened' : 'Not Opened');
                } else {
                    console.log("File doesn't exist.");
                }
            })
            .catch(error => {
                console.log(`getFile error: ${JSON.stringify(error)}`);
            });
    }
}

Component Template (app.component.html)

<StackLayout class="p-20" verticalAlignment="middle">  
    <Button text="Download and Open PDF" (tap)="downloadAndOpenPDF()" class="btn btn-primary btn-active"></Button>
</StackLayout>  

Screenshot

Using POST

In my real-world problem, I needed to use POST w/ URL encoded values to query my backend API. In this case, the first parameter of http.getFile() becomes:

{
    url: url,
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    content: "key1=value1&key2=value2"
}