I want to send a POST request containing JSON to a server for processing. The server will then return a PDF which I want to receive, save to the filesystem and display using nativescript-pdf-view. However, File.writeSync()
will not accept the ArrayBuffer that I get from the server response. Instead, it expects the native variants NSData (iOS) and ByteArray (Android). How can I convert the ArrayBuffer to the native byte arrays?
As explained by the official documentation, a POST request can be sent using the getBinary()
function:
import { getBinary } from 'tns-core-modules/http'
getBinary({
url: 'https://example.com/foo/bar/generate-pdf',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
content: JSON.stringify(someObject),
})
Here, someObject
is the object you want to convert to JSON and send to the server.
The response will contain the PDF or any other file as an ArrayBuffer. As mentioned in the question, the File.writeSync()
method expects NSData (iOS) and ByteArray (Android). So, we need to get a file handler, convert our file and save it to the filesystem.
import { getBinary } from 'tns-core-modules/http'
import { isAndroid } from 'tns-core-modules/platform'
import { File, knownFolders, path } from 'tns-core-modules/file-system'
getBinary({
url: 'https://example.com/foo/bar/generate-pdf',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
content: JSON.stringify(someObject),
}).then((buffer) => {
// Get file handler
const documentsFolder = knownFolders.documents()
const destination = path.join(documentsFolder.path, 'result.pdf')
const file = File.fromPath(destination)
// Convert buffer to byte array
let byteArray
if (isAndroid) {
byteArray = Array.create('byte', buffer.byteLength)
for (let i = 0; i < buffer.length; i++) {
byteArray[i] = new java.lang.Byte(buffer[i])
}
} else {
byteArray = NSData.dataWithBytesLength(buffer, buffer.byteLength)
}
// Save file
file.writeSync(byteArray, (error) => {
console.log(error)
});
})
Why the File.writeSync()
method doesn't convert this automatically is a miracle to me. Maybe someone else can explain!
To display the PDF, you can use nativescript-pdf-view. Just use the filehandler to get the path file.path
or the destination
variable and pass it to the src
property of the PDFView component. This might look like this:
<template>
<Page>
<ActionBar title="PDF" />
<GridLayout rows="*" columns="*">
<PDFView :src="path" row="0" col="0" />
</GridLayout>
</Page>
</template>
<script lang="ts">
export default {
name: 'PdfViewer',
props: {
path: {
type: String,
required: true,
},
},
}
</script>
Make sure to install the plugin, of course and introduce the element to Vue.js, first:
// main.ts
Vue.registerElement('PDFView', () => require('nativescript-pdf-view').PDFView)