Monday, 13 June 2011

How to stream a PDF and open at a specific page.

Today I need to open a streamed PDF to a user from a website and open it on a specified page. The website is written in PHP with the binary files stored in a non accessible directory so they need to be streamed to a user upon request.  This also allows for the website to check if you have access to a file and keep it private to the users in question.  So to open a PDF at a specific page you use a url like "http://domain/test.pdf#page=2" but since we are looking to stream a file you use a url like "http://domain/stream.php?id=<number>" which after checking you have access to the file runs something like

header("Content-Type: ". $ContentType);
$sStreamFilePath = STREAM_CACHE . "/file_".$DocumentId.".binaryFile";
header('Content-Disposition: attachment; filename="'.$filename.'"');
fpassthru(fopen($sStreamFilePath,'rb'));
exit();

 
So to open a PDF on a specific page we need to update the url to have "#page=<page>" on it "http://domain/stream.php?id=<number>#page=<page>"

Now your problem is that the hash part is not sent to the server so the stream.php never gets it. So you need to also pass it as a parameter like "http://domain/stream.php?id=<number>&page=<page>#page=<page>" this will send the page to the server which PHP will be able to access and add to the $iPageToOpenAt variable in the example below.

header("Content-Type: ". $ContentType);
$sStreamFilePath = STREAM_CACHE . "/file_".$DocumentId.".binaryFile";
if($ContentType=="application/pdf"){
 if($iPageToOpenAt != NOT_FOUND){
  header('Content-Disposition: attachment; filename="'.$filename.'#page='.$iPageToOpenAt.'"');
 } else {
  header('Content-Disposition: attachment; filename="'.$filename.'"');
 }
} else {
 header('Content-Disposition: attachment; filename="'.$filename.'"');
}
fpassthru(fopen($sStreamFilePath,'rb'));
exit();

What is actually happening is that we need to force both the browser and Acrobat Reader to see the page parameter.