PDF.js is a plugin for displaying pdfs in webpages, it solves a problem on ipads too(indirectly) where ipads and iphones only render first page of the pdf and users can't scroll pdfs rendered in iframes.
pdfjs_rails is the gem which we are going to use for integrating PDF.js in rails.
This gem is pretty old and not maintained, its last commit in master was 5 years ago(at the time of writing). But nevertheless it works and you can easily get you pdfs working in iPads and iPhone. tada!
There are only a few steps which i had to perform to get it working for S3 hosted files on non-public buckets.
You also have to use following CORS setting, as PDF.js sends an AJAX request after page load:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<ExposeHeader>Accept-Ranges</ExposeHeader>
<ExposeHeader>Content-Encoding</ExposeHeader>
<ExposeHeader>Content-Length</ExposeHeader>
<ExposeHeader>Content-Range</ExposeHeader>
<AllowedHeader>Range</AllowedHeader>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
- Install gem(follow its readme)
- Set CORS setting of your bucket as described above.
- As you have ran this command
rails g pdfjs_rails:install
while installing gem, this generates a lot of files. You can delete the locale files you dont need generated by this gem.
The real problem was in one of JS files genrated by this gem, which tries to parse url of the PDF file(hosted on S3 in our case). It was taking only small portion of url, ignoring all headers etc sent along the url.
To solve this problem, open the file: public/pdfjs/web/viewer.js
, generated by the gem. And on line number 3803
you should see following line, or search for this line otherwise:
document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
In this method it is parsing the url with some weird logic, which removes extra data from our S3 hosted PDF. I had to modify its first few lines to look something like:
document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
PDFView.initialize();
var params = document.location.search.substring(1);
var file = params.substr(5) || DEFAULT_URL;
params.substr(5)
is to remove file=
(5 characters) from the params.
Don't see any need to go into details of this change, you can analyze this code yourself. This is what is working for us now. You can put console logs in old code and new code to see whats different.
Happy coding!