0

I took the following piece of code from github

function smartReadFile($location, $filename, $mimeType = 'application/pdf')
{
  if (!file_exists($location))
  {
     header ("HTTP/1.1 404 Not Found");
     return;
  }
  $size = filesize($location);
  $time = date('r', filemtime($location));
  $fm       = @fopen($location, 'rb');
  if (!$fm)
  {
     header ("HTTP/1.1 505 Internal server error");
     return;
  }

  $begin    = 0;
  $end  = $size - 1;

  if (isset($_SERVER['HTTP_RANGE']))
  {
     if (preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches))
     {
        $begin  = intval($matches[1]);
        if (!empty($matches[2]))
        {
            $end    = intval($matches[2]);
        }
     }
  }

    if (isset($_SERVER['HTTP_RANGE']))
    {
       header('HTTP/1.1 206 Partial Content');
    }
    else
    {
       header('HTTP/1.1 200 OK');
    }

    header("Content-Type: $mimeType"); 
    header('Cache-Control: public, must-revalidate, max-age=0');
    header('Pragma: no-cache');  
    header('Accept-Ranges: bytes');
    header('Content-Length:' . (($end - $begin) + 1));
    if (isset($_SERVER['HTTP_RANGE']))
    {
       header("Content-Range: bytes $begin-$end/$size");
    }
    header("Content-Disposition: inline; filename=$filename");
    header("Content-Transfer-Encoding: binary");
    header("Last-Modified: $time");

    $cur    = $begin;
    fseek($fm, $begin, 0);

    while(!feof($fm) && $cur <= $end && (connection_status() == 0))
    {
      print fread($fm, min(1024 * 16, ($end - $cur) + 1));
      $cur += 1024 * 16;
    }
}

It is working for smaller files. But in case of large files it isn't working properly. I tried with a 100MB file. The PDF is partially loaded that too with a black background. I don't know what's wrong in the code. I suspect I had to modify the headers, but I don't know what to add/replace. I have tried many alternatives given in many sites, but none of them worked.

Thank you for any help

kumarp
  • 135
  • 3
  • 11
  • What error you have ? – WiatroBosy Jan 08 '21 at 09:23
  • @WiatroBosy no any error. But the PDF is loading partially that too with no content in it, with a black screen in the browser. Don't know why it is so, – kumarp Jan 08 '21 at 09:25
  • Start by checking the response in your browser dev tools (network panel), and see if there’s any PHP error messages getting output in there. (Enable proper PHP error reporting & display first, if you have not done that already.) – CBroe Jan 08 '21 at 09:26
  • @CBroe yeah I did that. In the browser console (Firefox), it is showing only 12MB is transferred. Any reason? – kumarp Jan 08 '21 at 09:31
  • I asked you to check for more than just the response size. Any errors/warnings/etc contained in the actual output? – CBroe Jan 08 '21 at 09:33
  • @CBroe Oh, sorry. In the response section, it is showing that the response has been truncated. – kumarp Jan 08 '21 at 09:36
  • But that’s just dev tools saying “I can’t display all of this”, I think. Try and remove the `Content-Type` and `Content-Disposition` headers, then the browser should display the response directly. – CBroe Jan 08 '21 at 09:39
  • 1
    Also, I am not sure how much sense trying to handle range requests makes here in the first place. Those make more sense when you do things like video streaming, or when download managers are supposed to be able to resume a broken-off transfer, or download using multiple connections in parallel. For the mere purpose of displaying a PDF directly in the browser, I don’t think it makes much sense. I’d try a simpler code maybe, that doesn’t bother with that kind of hassle. – CBroe Jan 08 '21 at 09:41
  • Have you tried simplifying things? Does it work if you remove the chunking while loop at the end and just use readfile() instead? It might be worth fiddling with the chunk size too, say 8k instead of 16k? – Andrew Paul Jan 08 '21 at 09:45
  • @CBroe yeah I did that. Loading the page took a lot of time but no content is being displayed in the browser. Also, there is no error message shown in the browser dev tools. – kumarp Jan 08 '21 at 10:03
  • @CBroe my idea is to hide the original URL of the file and show it's content in a different URL. – kumarp Jan 08 '21 at 10:04
  • If you don’t need to implement any access control checks at the same time, then it would probably make more sense to do that using URL rewriting. – CBroe Jan 08 '21 at 10:07
  • @CBroe I need to implement access control checks – kumarp Jan 08 '21 at 10:11
  • Try if a simpler code like https://stackoverflow.com/a/41206252/1427878 works. – CBroe Jan 08 '21 at 10:13
  • @AndrewPaul readfile can get memory restrictions for very large files. So I went with this idea. When I reduced the chunck size to 8k, file took it's time but loaded completely. But no content is shown in the browser, except a progress bar on top – kumarp Jan 08 '21 at 10:46
  • @AndrewPaul PDF file was successfully displayed when I reduced the data size further to 4k. Thank you for the idea – kumarp Jan 09 '21 at 16:45

0 Answers0