Today's Question:  What are you most afraid of as a programmer?        GIVE A SHOUT

Technical Article => Web =>  PHP

Output a file with HTTP range header in PHP

  sonic0002      2013-01-09 05:55:05      15,118    2    6

When downloading a large file, we may encounter some network issues which causes download termination and only part of the file is downloaded. When the network connection resumes next time, we may need to redownload the file again from the beginning. In order to save bandwidth, http provides a Range parameter in its header which can control the file transfer flow. With the range parameter in the header, we can resume the download from where we stop.

Here is a piece of PHP code snippet which uses the range header to control which part of the file to transfer:

    <?php
      $filename=$_GET['filename'];
      $location='media/'.$filename;
      
      $extension = substr(strrchr($filename,'.'),1);
      if ($extension == "mp3") {
        $mimeType = "audio/mpeg";
      } else if ($extension == "ogg") {
        $mimeType = "audio/ogg";
      }
      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;
      }

Here is the document of range : http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

The use of range : Usually it is used to resume file transfer process, also when you want to transfer a large file, you can use it to control partial file transfer to release the server IO pressure.

Source : http://cloudbbs.org/forum.php?mod=viewthread&tid=10764

PHP HTTP RANGE FILE TRANSFER

  SAVE AS PDF   MARK AS READ   MARK AS IMPORTANT

Share on Facebook  Share on Twitter  Share on Google+  Share on Weibo  Share on Reddit  Share on Digg  Share on Tumblr    Delicious

  RELATED


  2 COMMENTS


codefinder [Reply]@ 2015-03-01 13:12:10

in line 38 there is one empty too much...

sonic0002 [Reply]@ 2015-03-02 04:17:12

Thakn you. Have corrected it.


  WRITE ARTICLE

Press any key to boot

By rookie
Yesterday I was using a DVD to install an OS. In the meantime, the command line prompt asks to Press any key to boot. I searched the whole keyboard and didn"t find the any key. I was so frustrated that I hit the keyboard heavily. You know what? The reboot started and installation completed. What hap