2009-12-12 14 views
12

In primo luogo, sono a conoscenza di domande simili poste prima.PHP Streaming di file remoti con supporto di ripresa

Il soggetto spiega più o meno la domanda, ma ancora,

il file è ospitato su un altro server, l'utente dovrà scaricare il file tramite il mio script, in streaming a lui ...

Ma il problema è utente non posso riprenderlo una volta in pausa ... qualche soluzione?

risposta

1

Se si utilizza PHP per servire il file, è necessario implementare tutte le logiche di ripresa da soli.

Dovrai inviare Accept-Ranges e respond appropriately a Ranges.

Questo è un pezzo di lavoro. Potrebbe essere più facile usare mod_proxy.

1

Qual è lo scopo di questo? nascondere solo gli URL o solo consentire ai membri di scaricare?

Il modo in cui l'hai descritto, è un po 'complicato ...

  1. Il server remoto lo script scaricherà da dovrebbe supportare download di riprendere i.
  2. Lo script php deve verificare l'intestazione 'Accept-Range' & passarlo attraverso il server remoto (l'utilizzo di socket è l'opzione migliore immagino) in modo che lo script funzioni effettivamente come proxy.
17

Si può provare l'attuazione il proprio script scaricare utilizzando Accept-Ranges e Content-Range ecco un prof di concetto:

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

Utilizzo di Internet Download Manager

Inizio

Start

in pausa

Paused

stato di pausa

Paused State

Riprendi

Resume

Finito

enter image description here

classe utilizzata

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); 
     } 
    } 
} 

File Used

+0

Grazie! Mi hai aiutato molto !!! – HtmHell

+0

Prego :) – Baba

+0

greate job 1+ –

Problemi correlati