Implementing pdf.js in android to read from sd card - javascript

I'm trying to implement a pdf viewer for my android app which displays different pdf files which are present in the SD card.
I am thinking of using the pdf.js library.I used the code sample as posted here: https://bitbucket.org/butelo/pdfviewer/
However, the library takes the pdf url in the javascript file which is relative address to the folder to which it belongs (/assets/pdfviewer).
<script type="text/javascript">
var url = '../compressed.tracemonkey-pldi-09.pdf';
</script>
How can I redirect it to use a pdf present in a folder in the sdcard ?
Also the filenames of the pdfs are not fixed and I need to change them in the program as per requirement.
Update --------------------------------------------------------------------------------------------------------------------------
I updated the java code like this:
Uri path = Uri.parse(Environment.getExternalStorageDirectory().toString() + "/data/test.pdf");
webView.loadUrl("file:///android_asset/pdfviewer/index.html?file=" + path);
In the pdffile.js, I modified the following:
From:
<script type="text/javascript">
var url = '../compressed.tracemonkey-pldi-09.pdf';
</script>
To:
var url = getURLParameter('file');
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null}
The above javascript code extracts the 'file' parameter from the URL of the 'index.html'
Still does not work. The webview 'chromium' in logcat shows:
I/chromium(1353): [INFO:CONSOLE(106)] "Warning: Unhandled rejection:
Unexpected server response (0) while retrieving PDF "file:///storage/sdcard0/data/test.pdf".", source: file:///android_asset/pdfviewer/pdf.js (106)"
This seems to be cross server issue. So how can I modify the pdf.js code to read local files without server ?

Solved the issue. The app was missing READ_EXTERNAL_STORAGE permissions.
The code can be found at: https://github.com/pauldmps/Android-pdf.js
Its Apache V2 license, so feel free to use in your app.

Related

Window.location file download

I am trying to download a file to client side using following javascript code:
window.location = InsightRoute + "GetOrderXML?orderNumber=" + txtOrderNoVal
If the file is available then it will get downloaded to the client machine. But the issues is if no file is available for downloading, it
will simply gets redirect to a blank page
http://mysite/GetOrderXML?orderNumber=1
You should check whether the file is available for downloading before redirecting, for example like this:
if (sdpInsightRoute && txtOrderNoVal)
window.location = sdpInsightRoute + "GetOrderXML?orderNumber=" + txtOrderNoVal
This way, if the variable txtOrderNoVal is undefined, the redirection wouldn't take place.
If file is not available then use following code inside controller, so that the alert will pop up:
Response.Write("<script>alert('Item does not exist on this environment.');window.history.go(-1);</script>");
return null;
Use of: window.history.go(-1); If there is no file and since it is getting redirected to a new page: http://mysite/Insight/GetOrderXML?orderNumber=1, which can be avoided.

Not able to render pdf by passing Uint8Array in the viewer.html file parameter while using pdfjs

I am trying to create an app with electron and react in which I am trying to render a pdf using pdfjs from the local filesystem. I will get the pdf data from electron which will then be passed to react app.
After going through the code for viewer.js file I can see that I can send the file parameter value as Uint8Array and in turn, it will call the PDFJS's getDocument with data, so I tried a little example but somehow I am not able to get it working.
Pasting the code below
base64ToUint8Array = () => {
// taken from pdfjs github example
let raw = atob(
'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' +
'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' +
'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' +
'Pj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAg' +
'L1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+' +
'PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9u' +
'dAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2Jq' +
'Cgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJU' +
'CjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVu' +
'ZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4g' +
'CjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAw' +
'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G');
let uint8Array = new Uint8Array(new ArrayBuffer(raw.length));
for (var i = 0; i < raw.length; i++) {
uint8Array[i] = raw.charCodeAt(i);
}
return uint8Array;
render(){
let pdfUint8Array = this.base64ToUint8Array();
return(
<iframe
src={`/web/viewer.html?file=${pdfUint8Array}`}
title="frame"
width="100%"
height="700px"
/>
);
}
From the error on the browser console I can see that the file param value is still taken as url hence pdf not getting rendered.
Error
fetch_stream.js:101 GET http://localhost:3001/web/37,80,68,70,45,49,46,55,10,10,49,32,48,32,111,98,106,32,32,37,32,101,110,116,114,121,32,112,111,105,110,116,10,60,60,10,32,32,47,84,121,112,101,32,47,67,97,116,97,108,111,103,10,32,32,47,80,97,103,101,115,32,50,32,48,32,82,10,62,62,10,101,110,100,111,98,106,10,10,50,32,48,32,111,98,106,10,60,60,10,32,32,47,84,121,112,101,32,47,80,97,103,101,115,10,32,32,47,77,101,100,105,97,66,111,120,32,91,32,48,32,48,32,50,48,48,32,50,48,48,32,93,10,32,32,47,67,111,117,110,116,32,49,10,32,32,47,75,105,100,115,32,91,32,51,32,48,32,82,32,93,10,62,62,10,101,110,100,111,98,106,10,10,51,32,48,32,111,98,106,10,60,60,10,32,32,47,84,121,112,101,32,47,80,97,103,101,10,32,32,47,80,97,114,101,110,116,32,50,32,48,32,82,10,32,32,47,82,101,115,111,117,114,99,101,115,32,60,60,10,32,32,32,32,47,70,111,110,116,32,60,60,10,32,32,32,32,32,32,47,70,49,32,52,32,48,32,82,32,10,32,32,32,32,62,62,10,32,32,62,62,10,32,32,47,67,111,110,116,101,110,116,115,32,53,32,48,32,82,10,62,62,10,101,110,100,111,98,106,10,10,52,32,48,32,111,98,106,10,60,60,10,32,32,47,84,121,112,101,32,47,70,111,110,116,10,32,32,47,83,117,98,116,121,112,101,32,47,84,121,112,101,49,10,32,32,47,66,97,115,101,70,111,110,116,32,47,84,105,109,101,115,45,82,111,109,97,110,10,62,62,10,101,110,100,111,98,106,10,10,53,32,48,32,111,98,106,32,32,37,32,112,97,103,101,32,99,111,110,116,101,110,116,10,60,60,10,32,32,47,76,101,110,103,116,104,32,52,52,10,62,62,10,115,116,114,101,97,109,10,66,84,10,55,48,32,53,48,32,84,68,10,47,70,49,32,49,50,32,84,102,10,40,72,101,108,108,111,44,32,119,111,114,108,100,33,41,32,84,106,10,69,84,10,101,110,100,115,116,114,101,97,109,10,101,110,100,111,98,106,10,10,120,114,101,102,10,48,32,54,10,48,48,48,48,48,48,48,48,48,48,32,54,53,53,51,53,32,102,32,10,48,48,48,48,48,48,48,48,49,48,32,48,48,48,48,48,32,110,32,10,48,48,48,48,48,48,48,48,55,57,32,48,48,48,48,48,32,110,32,10,48,48,48,48,48,48,48,49,55,51,32,48,48,48,48,48,32,110,32,10,48,48,48,48,48,48,48,51,48,49,32,48,48,48,48,48,32,110,32,10,48,48,48,48,48,48,48,51,56,48,32,48,48,48,48,48,32,110,32,10,116,114,97,105,108,101,114,10,60,60,10,32,32,47,83,105,122,101,32,54,10,32,32,47,82,111,111,116,32,49,32,48,32,82,10,62,62,10,115,116,97,114,116,120,114,101,102,10,52,57,50,10,37,37,69,79,70 404 (Not Found)
I can also see while console logging the file param as file [object ArrayBuffer] if I pass pdfUint8Array.buffer in the file param but the pdf is still isn't rendered as it is taken as a string as pdfjs try to display it with url.
CodeSAndbox Demo (open the result of the codesandbox in a new tab for it
to work)
Hey Hiten,
Apparently in mozilla official documents for PDF.js, They say that no need to convert to Byte array (uint8Array), you can parse the base64 code into pdf directly....
Just render the iframe with data:application/pdf;base64 before the raw base64 data like this and it will appear :)
<iframe
title="frame"
width="300px"
height="700px"
src={`data:application/pdf;base64,${this.base64PDF()}`} />
A good reference in another Stackoverflow Thread discussing rendering a pdf file using a base64 instead of url
I hope I have helped you ✌
My main aim here was to render the pdf from my local filesystem in the electron app that I am creating.
My earlier approach was to pass on the raw base64 data of the pdf in an iframe with src as web/viewer.html of the pdfjs but due to some limitation in electron, this wasn't working.
So, I figured out an easy solution that while starting electron I ran a node server on the directory from where I wanted to serve the pdf files and used the URL in the form http://localhost/{port_number}/{path_to_my_pdf_files} to access the pdf in pdfjs
<iframe
src={`/web/viewer.html?file=http://localhost:${process.env.REACT_APP_PDF_SERVER_PORT}/${path}`}
title="iframe"
width="100%"
height="700px"
/>

Installing firefox extension on a web site

I have created an extension for mozilla firefox. Now, I'm trying to distribute the extension on an simple web site. I generate a sha1 hash code from an online generator. This is the code I have in my web site:
<script type="application/javascript">
function install (aEvent)
{
for (var a = aEvent.target; a.href === undefined;) a = a.parentNode;
var params = {
"Foo": { URL: aEvent.target.href,
Hash: aEvent.target.getAttribute("hash"),
toString: function () { return this.URL; }
}
};
InstallTrigger.install(params);
return false;
}
</script>
<a href="c:/grouAndUsersWorkSpace/MozillaAddon/createtab.xpi"
hash="sha1:a7093a2afe1a53fde114a4a7dcb3e15e57862642"
onclick="return install(event);">Install Extension!</a>
the path of the url is local. And as a result when I start the application I got "The add-on could not be downloaded because of a connection failure on localhost".
I changed the path of the url to be: file://c:/grouAndUsersWorkSpace/MozillaAddon/createtab.xpi and with this nothing happens.
I have two questions:
1. Is that a good way to generate a hash code?
2. What should cause that connection failure?
1) I prefer to use the CHK Checksum Utility to generate checksums.
2) I don't have access at the moment to verify it, but have you tried serving the extension with Apache or similar?
Edit
Since you used a local file, you'll need a 3 slashes instead of 2 : file URI scheme .
Tested it both ways, they both work.

How to fetch file content (basically read) a local file in javascript for UIAutomation iOS

Is there a possible way to read a local file in JavaScript.
MyFolder:
db.csv
Parse.js
Trying to fetch the contents of file db.csv in Parse.js, But in vain.
Can you share some links where I can get enough knowledge how to read a file.
Running Instruments in Xcode5, with test scripts in .js file where I have to feed in some values from a .csv file.
iOS UIAutomation, apple provides an api for running a task on the target's host.
performTaskWithPathArgumentsTimeout
Using this, we can have a bash script to printout the contents of a file that we wanted to fetch in the first case.
Bash script can be as simple as this for this requirement.
#! /bin/bash
FILE_NAME="$1"
cat $FILE_NAME
Save it as for example FileReader.sh file.
And in your automation script,
var target = UIATarget.localTarget();
var host = target.host();
var result = host.performTaskWithPathArgumentsTimeout(executablePath,[filePath,fileName], 15);
UIALogger.logDebug("exitCode: " + result.exitCode);
UIALogger.logDebug("stdout: " + result.stdout);
UIALogger.logDebug("stderr: " + result.stderr);
where in,
executablePath is where the command need to be executed.
var executablePath = "/bin/sh";
filePath is the location of the created FileReader.sh file. When executed, outputs the content to standard output (in our requirement).
[give full absolute path of the file]
fileName is the actual file to fetch contents from.
[give full absolute path of the file] In my case I had a Contents.csv file, which I had to read.
and the last parameter is the timeout in seconds.
Hope this helps others, trying to fetch contents (reading files) for performing iOS UIAutomation.
References:
https://stackoverflow.com/a/19016573/344798
https://developer.apple.com/library/iOS/documentation/UIAutomation/Reference/UIAHostClassReference/UIAHost/UIAHost.html
If the file is on the same domain as the site you're in, you'd load it with Ajax. If you're using Ajax, it's be something like
$.get('db.csv', function(csvContent){
//process here
});
Just note that the path to the csv file will be relative to the web page you're in, not the JavaScript file.
If you're not using jQuery, you'd have to manually work with an XmlHttpRequest object to do your Ajax call.
And though your question doesn't (seem to) deal with it, if the file is located on a different domain, then you'd have to use either jsonP or CORS.
And, just in case this is your goal, no, you can't, in client side JavaScript open up some sort of Stream and read in a file. That would be a monstrous security vulnerability.
This is a fairly simple function in Illuminator's host functions library:
function readFromFile(path) {
var result = target.host().performTaskWithPathArgumentsTimeout("/bin/cat", [path], 10);
// be verbose if something didn't go well
if (0 != result.exitCode) {
throw new Error("readFromFile failed: " + result.stderr);
}
return result.stdout;
}
If you are using Illuminator, this is host().readFromFile(path).

Do we need a web server (like Apache) to access a .json file?

I was trying to read an info.json file, using the jQuery API. Please find the code below, which is part of test.html.
$.getJSON('info.json', function(data) {
var items = [];
$.each(data, function(key, val) {
items.push('<li id="' + key + '">' + val + '</li>');
});
The test.html file resides on my local machine and when I try to open it in the browser, the Ajax call is not getting triggered and the info.json file is not read.
Is it not working because I don't have a web server? Or am I doing anything wrong in the code? (I don't see any errors in the Firebug console though).
Thanks in advance.
You will always have to host your site from where you are making AJAX call. Otherwise it will throw this exception.
origin null is not allowed by access-control-allow-origin
Host your page on localhost server and I guess everything will work nicely.
While technically you don't need a web server for this, some of the libraries you use to abstract network access may not work with local files and some browsers don't let local files do a lot, so something like a little test web server for static files would be very useful for your development and testing.
Install a small webserver like http://jetty.codehaus.org/jetty/
easy to install, and small download ;)
By putting your JSON string into a text file and loading it in a iframe, you can extrapolate the data. (Most browsers can load .txt files in iframes.)
var frame = document.createElement("IFRAME"); //Create new iframe
var body = document.body;
frame.onload = function() { //Extrapolate JSON once loaded
data = JSON.parse(frame.contentDocument.documentElement.innerText); //Loads as a global.
body.removeChild(frame); //Removes the frame once no longer necessary.
}
frame.style.display = "none"; //Because the frame will have to be appended to the body.
body.appendChild(frame);
frame.src = "your JSON.txt"; //Select source after the onload function is set.

Categories

Resources