2009-12-12 6 views
12

Erstens ist mir bewusst, dass ähnliche Frage zuvor gestellt wird.PHP Remote-Datei-Streaming mit Resume-Unterstützung

Das Thema erklärt so ziemlich die Frage, aber immer noch,

die Datei auf einem anderen Server gehostet wird, wird die Benutzer-Datei über mein Skript herunterladen, er strömte ...

Aber das Problem ist Benutzer kann es nicht fortsetzen, wenn es unterbrochen wurde ... irgendwelche Lösungen?

Antwort

1

Wenn Sie PHP verwenden, um die Datei zu liefern, müssen Sie alle Wiederaufnahme-Logik selbst implementieren.

Sie müssen Accept-Ranges und respond appropriately an Ranges senden.

Das ist ein Stück Arbeit. Es könnte einfacher sein, mod_proxy zu verwenden.

1

Was ist der Zweck? URLs nur verstecken oder nur Mitgliedern erlauben, herunterzuladen?

Die Art und Weise Sie es beschrieben ist, ist es ein bisschen schwierig ...

  1. Der Remote-Server Ihr Skript aus sollte unterstützen Fortsetzen von Downloads heruntergeladen.
  2. Ihr PHP-Skript sollte auf "Accept-Range" Header & überprüfen, um es an den Remote-Server übergeben (mit Sockets ist Ihre beste Option, denke ich), so dass Ihr Skript tatsächlich als Proxy fungiert.
17

Sie können versuchen, Ihre eigenen Download-Skript mit Accept-Ranges und Content-Range hier ist ein prof der Umsetzung des Konzepts:

set_time_limit(0); 
$download = new ResumeDownload("word.dir.txt", 50000); //delay about in microsecs 
$download->process(); 

Verwenden von Internet Download Manager

starten

Start

Paused

Paused

Paused Staat

Paused State

Lebenslauf

Resume

enter image description here

Klasse verwendet

class ResumeDownload { 
    private $file; 
    private $name; 
    private $boundary; 
    private $delay = 0; 
    private $size = 0; 

    function __construct($file, $delay = 0) { 
     if (! is_file($file)) { 
      header("HTTP/1.1 400 Invalid Request"); 
      die("<h3>File Not Found</h3>"); 
     } 

     $this->size = filesize($file); 
     $this->file = fopen($file, "r"); 
     $this->boundary = md5($file); 
     $this->delay = $delay; 
     $this->name = basename($file); 
    } 

    public function process() { 
     $ranges = NULL; 
     $t = 0; 
     if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_SERVER['HTTP_RANGE']) && $range = stristr(trim($_SERVER['HTTP_RANGE']), 'bytes=')) { 
      $range = substr($range, 6); 
      $ranges = explode(',', $range); 
      $t = count($ranges); 
     } 

     header("Accept-Ranges: bytes"); 
     header("Content-Type: application/octet-stream"); 
     header("Content-Transfer-Encoding: binary"); 
     header(sprintf('Content-Disposition: attachment; filename="%s"', $this->name)); 

     if ($t > 0) { 
      header("HTTP/1.1 206 Partial content"); 
      $t === 1 ? $this->pushSingle($range) : $this->pushMulti($ranges); 
     } else { 
      header("Content-Length: " . $this->size); 
      $this->readFile(); 
     } 

     flush(); 
    } 

    private function pushSingle($range) { 
     $start = $end = 0; 
     $this->getRange($range, $start, $end); 
     header("Content-Length: " . ($end - $start + 1)); 
     header(sprintf("Content-Range: bytes %d-%d/%d", $start, $end, $this->size)); 
     fseek($this->file, $start); 
     $this->readBuffer($end - $start + 1); 
     $this->readFile(); 
    } 

    private function pushMulti($ranges) { 
     $length = $start = $end = 0; 
     $output = ""; 

     $tl = "Content-type: application/octet-stream\r\n"; 
     $formatRange = "Content-range: bytes %d-%d/%d\r\n\r\n"; 

     foreach ($ranges as $range) { 
      $this->getRange($range, $start, $end); 
      $length += strlen("\r\n--$this->boundary\r\n"); 
      $length += strlen($tl); 
      $length += strlen(sprintf($formatRange, $start, $end, $this->size)); 
      $length += $end - $start + 1; 
     } 
     $length += strlen("\r\n--$this->boundary--\r\n"); 
     header("Content-Length: $length"); 
     header("Content-Type: multipart/x-byteranges; boundary=$this->boundary"); 
     foreach ($ranges as $range) { 
      $this->getRange($range, $start, $end); 
      echo "\r\n--$this->boundary\r\n"; 
      echo $tl; 
      echo sprintf($formatRange, $start, $end, $this->size); 
      fseek($this->file, $start); 
      $this->readBuffer($end - $start + 1); 
     } 
     echo "\r\n--$this->boundary--\r\n"; 
    } 

    private function getRange($range, &$start, &$end) { 
     list($start, $end) = explode('-', $range); 

     $fileSize = $this->size; 
     if ($start == '') { 
      $tmp = $end; 
      $end = $fileSize - 1; 
      $start = $fileSize - $tmp; 
      if ($start < 0) 
       $start = 0; 
     } else { 
      if ($end == '' || $end > $fileSize - 1) 
       $end = $fileSize - 1; 
     } 

     if ($start > $end) { 
      header("Status: 416 Requested range not satisfiable"); 
      header("Content-Range: */" . $fileSize); 
      exit(); 
     } 

     return array(
       $start, 
       $end 
     ); 
    } 

    private function readFile() { 
     while (! feof($this->file)) { 
      echo fgets($this->file); 
      flush(); 
      usleep($this->delay); 
     } 
    } 

    private function readBuffer($bytes, $size = 1024) { 
     $bytesLeft = $bytes; 
     while ($bytesLeft > 0 && ! feof($this->file)) { 
      $bytesLeft > $size ? $bytesRead = $size : $bytesRead = $bytesLeft; 
      $bytesLeft -= $bytesRead; 
      echo fread($this->file, $bytesRead); 
      flush(); 
      usleep($this->delay); 
     } 
    } 
} 
Finished

File Used

+0

Dank! Sie haben mir sehr geholfen !!! – HtmHell

+0

Sie sind herzlich willkommen :) – Baba

+0

realy greate job 1+ –