I'm trying to call a JavaScript-Method from within my JavaFX-WebView via:
JSObject win = (JSObject)getEngine().executeScript("window");
win.call("showPDF", myPDFFile /*typeof java.io.File*/);
the result of this call is:
Invalid parameter object: need either .data, .range or .url
This is the JavaScript-Part (not by me), which throws the error:
var source;
if (typeof src === 'string') {
source = { url: src };
} else if (isArrayBuffer(src)) {
source = { data: src };
} else if (src instanceof PDFDataRangeTransport) {
source = { range: src };
} else {
if (typeof src !== 'object') {
error('Invalid parameter in getDocument, need either Uint8Array, ' +
'string or a parameter object');
}
if (!src.url && !src.data && !src.range) {
error('Invalid parameter object: need either .data, .range or .url');
}
}
Implementation of isArrayBuffer
:
function isArrayBuffer(v) {
return typeof v === 'object' && v !== null && v.byteLength !== undefined;
}
So my question is:
What type of (java) object could be used so that this call might work?
win.call("showPDF", ???);
EDIT 1:
String cannot be used, because it will be treated as a URL.
I would like to commit something like a ByteArray (my concrete file), but using a byte[]
(instead of java.io.File
) causes the same error.
Here are some comments from the JS function above:
https://github.com/mozilla/pdf.js/blob/master/src/display/api.js#L234
This is the main entry point for loading a PDF and interacting with it.
NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
is used, which means it must follow the same origin rules that any XHR does
e.g. No cross domain requests without CORS.
@param {string|TypedArray|DocumentInitParameters|PDFDataRangeTransport} src
Can be a url to where a PDF is located, a typed array (Uint8Array)
already populated with data or parameter object.
What Datatype i have to use (in JAVA), so it will be a (e.g) TypedArray (Uint8Array) in JAVASCRIPT?
EDIT 2:
I was trying Aarons suggestion:
String encoded = Base64.getEncoder().encodeToString(Files.readAllBytes(myPDFFile.toPath()));
engine.executeScript("var src = _base64ToArrayBuffer('"+encoded+"'); showPDF(src);");
This causes a new problem:
Error: Invalid PDF binary data: either typed array, string or array-like object is expected in the data property.
This (new) error is thrown (few lines later) here: https://github.com/mozilla/pdf.js/blob/master/src/display/api.js#L291
console.log(_base64ToArrayBuffer(encoded))
returns: [object ArrayBuffer]
Solution:
I managed to make this work (with help of Aaron):
pdfViewer.html
<!doctype html>
<html>
<head>
<script src="web/compatibility.js"></script>
<script src="build/pdf.js"></script>
<script>
function _base64ToBinaryString(base64) {
var binary_string = window.atob(base64);
return binary_string;
}
function showPDF(pdfFile) {
console.log('calling showPDF...');
'use strict';
PDFJS.disableWorker = true; /* IMPORTANT TO DISABLE! */
PDFJS.workerSrc = 'build/pdf.worker.js';
console.log('TRYING TO GET DOCUMENT FROM BINARY DATA...');
PDFJS.getDocument({data: pdfFile}).then(function(pdf)
{
console.log('PDF LOADED.');
console.log('TRYING TO GET PAGE 1...');
pdf.getPage(1).then(function(page) {
console.log('PAGE 1 LOADED.');
var scale = 1.0;
var viewport = page.getViewport(scale);
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: context,
viewport: viewport
};
console.log('RENDERING PAGE 1...');
page.render(renderContext);
});
});
};
</script>
</head>
<body>
<canvas id="the-canvas" style="border:1px solid black;"/>
</body>
</html>
After loading the above HTML-Page into the WebView, following Java-Code is used to load a PDF-File into the Page:
String encoded = Base64.getEncoder().encodeToString(Files.readAllBytes(myPdfFile.toPath()));
webEngine.executeScript("var src = _base64ToBinaryString('"+encoded+"'); showPDF(src);");