Index: file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.102
diff -u -p -r1.102 file.inc
--- file.inc	2 Jul 2007 14:41:35 -0000	1.102
+++ file.inc	4 Jul 2007 18:04:07 -0000
@@ -799,10 +799,50 @@ function file_transfer($source, $headers
 
   $source = file_create_path($source);
 
-  // Transfer file in 1024 byte chunks to save memory usage.
   if ($fd = fopen($source, 'rb')) {
+    // Tell client that we accept byte ranges.
+    drupal_set_header('Accept-Ranges: bytes');
+    // Get file size.
+    $filesize = filesize($source);
+    // Is this a partial request?
+    if (isset($_SERVER['HTTP_RANGE'])) {
+      if (preg_match('/^bytes=(\d+)-(\d+)$/', $_SERVER['HTTP_RANGE'], $match)) {
+        $range_from = $match[1];
+        $range_to = $match[2];
+        if ($range_to + 1 >= $filesize || $range_from >= $range_to) {
+          drupal_set_header('416 Requested Range Not Satisfiable');
+          $range_from = 0;
+          $range_to = $filesize - 1;
+        }
+        else {
+          drupal_set_header('HTTP/1.1 206 Partial Content');
+          // Move file pointer.
+          fseek($fd, $range_from);
+        }
+      }
+      else {
+        drupal_set_header('416 Requested Range Not Satisfiable');
+        $range_from = 0;
+        $range_to = $filesize - 1;
+      }
+      $r = $range_to - $range_from + 1;
+      drupal_set_header(sprintf('Content-Range: bytes %d-%d/%d', $range_from, $range_to, $filesize));
+      drupal_set_header('Content-Length: '. $r);
+    }
+    else {
+      $r = $filesize;
+      drupal_set_header('Content-Length: '. $filesize);
+    }
+    // Transfer file in 1024 byte chunks to save memory.
     while (!feof($fd)) {
-      print fread($fd, 1024);
+      if ($r >= 1024) {
+        $r = $r - 1024;
+        print fread($fd, 1024);
+      }
+      else {
+        print fread($fd, $r);
+        break;
+      }
     }
     fclose($fd);
   }
