3

I want to show a PDF file generated with pdfMake with the nativescript-pdf-view plugin in a NativeScript-Vue app.

I am unable to show the file inside the plugin widget. I started from this example, but I want to display the file inside the app.

First I generate encode the PDF to base64, which works fine, then I write the encoded string to file. When I pass the file path to the widget nothing shows up. URLs are shown correctly, so the error might happen while writing to file or handling the path.


PDF generation (app/scripts/pdf.js):

import { createPdf } from "pdfmake/build/pdfmake";
import { pdfMake } from "pdfmake/build/vfs_fonts";
import { knownFolders } from "tns-core-modules/file-system";

export default {
    generatePdf() {
        return new Promise((resolve, reject) => {

            var docDefinition = {
                pageSize: "A5",
                pageMargins: [40, 40, 40, 40],
                content: { text: "Test", fontSize: 80 }
            };

            var file = knownFolders.documents().getFile("document1.pdf");

            createPdf(docDefinition, "", "", pdfMake.vfs).getBase64(base64 => {
                // decoding this string returns a correct pdf file

                file.writeText(base64).then(() => {
                    // file properties are updated

                    resolve(file.path);
                    // path example: "/data/user/0/{app package}/files/document1.pdf"

                }).catch(e => reject(e));
            });
        });
    },

    // other code
}

Component:

<template>
    <GridLayout rows="* *">
        <Button row="0" @tap="getPDF" text="get pdf" />
        <PDFView row="1" :src="pdf" />
    </GridLayout>
</template>

<script>
import pdfModule from "../scripts/pdf";

export default {
    data() {
        pdf: ""
    },
    methods: {
        async getPDF() {
            this.pdf = await pdfModule.generatePdf().catch(e => console.error(e));
        }
    }
}
</script>
TomG
  • 538
  • 4
  • 20
  • 1
    You are not suppose to write base64 string to file. If you want to write data to file it should be binary, generally base64 string is used by browser / webview. It's an alternate for binary file. – Manoj Dec 23 '19 at 13:02
  • Ok, I see that writeText does not accept base64 strings. Now I am trying to write a Uint8Array with `writeSync`, but I get an error on `java.io.FileOutputStream` – TomG Dec 23 '19 at 15:49
  • I was able to achieve this on Android using a native Byte array. Right now I need a code snippet for converting the byte array to ios NSData. – TomG Dec 23 '19 at 16:54
  • 1
    You could use the syntax `NSData.dataWithBytesLength(bytePointer, length)`. – Manoj Dec 23 '19 at 17:06

1 Answers1

4

Solved using native byte arrays.

import { createPdf } from "pdfmake/build/pdfmake";
import { pdfMake } from "pdfmake/build/vfs_fonts";
import { knownFolders } from "tns-core-modules/file-system";
import { isAndroid } from "tns-core-modules/platform";

export default {

    generatePdf() {
        return new Promise((resolve, reject) => {

            let docDefinition = {
                pageSize: "A5",
                pageMargins: [40, 40, 40, 40],
                content: { text: "Test", fontSize: 80 }
            };

            let file = knownFolders.documents().getFile("document1.pdf");

            createPdf(docDefinition, "", "", pdfMake.vfs).getBuffer(result => {

                file.writeSync(this._bufferToNativeArray(result), e => {
                    console.error(e);
                    reject(e);
                });

                resolve(file.path);
            });
        });
    },

    _bufferToNativeArray(byteArray) {
        let array;

        if (isAndroid) {
            array = Array.create("byte", byteArray.byteLength);
            for (let i = 0; i < byteArray.length; i++) {
                array[i] = new java.lang.Byte(byteArray[i]);
            }
        } else {
            array = NSData.dataWithBytesLength(byteArray, byteArray.byteLength);
        }

        return array;
    }

}   
TomG
  • 538
  • 4
  • 20