subramanian rasapan subramanian rasapan - 19 days ago 10
Javascript Question

How to set range header from client with pdf.js?

I am quite new to client side programming. I am trying to view my pdf in my web using pdf.js. By following the steps in documentation i tried loading pdf with pdf.js. The entire pdf file is getting downloaded in a single request. Now, I would like to do progressive loading (downloading by specifying the range).

I have done the following things at my client and server side.

My client contains two files


  1. form.js and

  2. index.html



CLIENT
form.js

'use strict';
var PDF_PATH = ""; //Path of pdf file in web
var PAGE_NUMBER = 1;
var PAGE_SCALE = 1.5;

function renderPage(div, pdf, pageNumber, callback) {
pdf.getPage(pageNumber).then(function(page) {
var scale = 1.5;
var viewport = page.getViewport(scale);

var pageDisplayWidth = viewport.width;
var pageDisplayHeight = viewport.height;

var pageDivHolder = document.createElement('div');
pageDivHolder.className = 'pdfpage';
pageDivHolder.style.width = pageDisplayWidth + 'px';
pageDivHolder.style.height = pageDisplayHeight + 'px';
div.appendChild(pageDivHolder);

// Prepare canvas using PDF page dimensions
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = pageDisplayWidth;
canvas.height = pageDisplayHeight;
pageDivHolder.appendChild(canvas);

// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext).promise.then(callback);

// Prepare and populate form elements layer
var formDiv = document.createElement('div');
pageDivHolder.appendChild(formDiv);

//setupForm(formDiv, page, viewport);
});
}


function pageLoaded() {
PDFJS.disableWorker = true;
PDFJS.workerSrc = "./pdf.worker.js"; // no i18n
PDFJS.getDocument({url: PDF_PATH}).then(function (pdf) {

var canvas = document.createElement("canvas");
canvas.setAttribute("id", "pageCanvas");
canvas.setAttribute('style', "display:none");
document.body.appendChild(canvas);

// Rendering all pages starting from first
var viewer = document.getElementById('viewer');
var pageNumber = 1;
renderPage(viewer, pdf, pageNumber++, function pageRenderingComplete() {
if (pageNumber > pdf.numPages) {
return; // All pages rendered
}
// Continue rendering of the next page
renderPage(viewer, pdf, pageNumber++, pageRenderingComplete);
});
});
}

document.addEventListener('DOMContentLoaded', function () {
if (typeof PDFJS === 'undefined') {
alert('Built version of PDF.js was not found.\n' +
'Please run `gulp generic`.');
return;
}


and my index.html just loads the above js (form.js) and pdf.js and pdf.worker.js files

SERVER

This contains a servlet in which i have done the following


  1. Option to seek and read the file content from specific byte range by obtaining value from "Range" header in the request

  2. Have added
    Accept-Range:Bytes
    and
    Access-Control-Allow-Headers:Accept-Ranges
    values in response headers



Now I got struck in the following


1.Where to add "Range" header value?

2.How to send range request from client?

3.From where these calls were made?

4.Should I include viewer.html?


Please help me with this ! I'm collapsed :-(

Answer

1.Where to add "Range" header value?

PDF.js detects if server returns "Accept-Ranges:Bytes" If server returns valid HTTP request headers (per spec), PDF.js (will abort main requests for platforms that does not allow incremental XHR and) will issue range requests.

2.How to send range request from client?

PDF.js does that automatically via XHR when it decides that server can handle range requests.

3.From where these calls were made?

See network.js file.

4.Should I include viewer.html?

No

Looks like currently the servlet that provides PDF data does not support valid HTTP range request protocol. Just setting "Accept-Range:Bytes" is not enough. See how it's implemented in PHP at or check previously answered question related to servlets.