2013-03-30 124 views
1

我需要直接向客戶端下載遠程文件。一些谷歌搜索後,我發現這個腳本在PHP手冊,但其恢復能力不起作用。該腳本使用Http_Range生成可恢復的下載鏈接。有沒有其他方法可以做到這一點?當然,這將使用cUrl,但我需要將遠程文件直接下載到客戶端。我該如何解決這個問題?將遠程文件直接下載到客戶端?

<?php   
$url="http://dl.remote-domain.com/files/file.mp4"; 
dl_file_resumable($url); 

function dl_file_resumable($file, $is_resume=TRUE) 
{ 


    //Gather relevent info about file 
    $size = remotefilesize($file); 
    $fileinfo = pathinfo($file); 

    //workaround for IE filename bug with multiple periods/multiple dots in filename 
    //that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe 
    $filename = (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ? 
        preg_replace('/\./', '%2e', $fileinfo['basename'], substr_count($fileinfo 

['basename'], '.') - 1) : 
        $fileinfo['basename']; 

    $file_extension = strtolower($path_info['extension']); 

    //This will set the Content-Type to the appropriate setting for the file 
    switch($file_extension) 
    { 
     case 'exe': $ctype='application/octet-stream'; break; 
     case 'zip': $ctype='application/zip'; break; 
     case 'mp3': $ctype='audio/mpeg'; break; 
     case 'mpg': $ctype='video/mpeg'; break; 
     case 'avi': $ctype='video/x-msvideo'; break; 
     default: $ctype='application/force-download'; 
    } 

    //check if http_range is sent by browser (or download manager) 
    if($is_resume && isset($_SERVER['HTTP_RANGE'])) 
    { 
     list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2); 

     if ($size_unit == 'bytes') 
     { 
      //multiple ranges could be specified at the same time, but for simplicity only 

serve the first range 
      //http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt 
      list($range, $extra_ranges) = explode(',', $range_orig, 2); 
     } 
     else 
     { 
      $range = ''; 
     } 
    } 
    else 
    { 
     $range = ''; 
    } 

    //figure out download piece from range (if set) 
    list($seek_start, $seek_end) = explode('-', $range, 2); 

    //set start and end based on range (if set), else set defaults 
    //also check for invalid ranges. 
    $seek_end = (empty($seek_end)) ? ($size - 1) : min(abs(intval($seek_end)),($size - 1)); 
    $seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs 

(intval($seek_start)),0); 

    //add headers if resumable 
    if ($is_resume) 
    { 
     //Only send partial content header if downloading a piece of the file (IE workaround) 
     if ($seek_start > 0 || $seek_end < ($size - 1)) 
     { 
      header('HTTP/1.1 206 Partial Content'); 
     } 

     header('Accept-Ranges: bytes'); 
     header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$size); 
    } 

    //headers for IE Bugs (is this necessary?) 
    //header("Cache-Control: cache, must-revalidate"); 
    //header("Pragma: public"); 

    header('Content-Type: ' . $ctype); 
    header('Content-Disposition: attachment; filename="' . $filename . '"'); 
    header('Content-Length: '.($seek_end - $seek_start + 1)); 

    //open the file 
    $fp = fopen($file, 'rb'); 
    //seek to start of missing part 
    fseek($fp, $seek_start); 

    //start buffered download 
    while(!feof($fp)) 
    { 
     //reset time limit for big files 
     set_time_limit(0); 
     print(fread($fp, 1024*8)); 
     flush(); 
     ob_flush(); 
    } 

    fclose($fp); 
    exit; 
} 

function remotefilesize($url, $user = "", $pw = "") 
{ 
    ob_start(); 
    $ch = curl_init($url); 
    curl_setopt($ch, CURLOPT_HEADER, 1); 
    curl_setopt($ch, CURLOPT_NOBODY, 1); 

    if(!empty($user) && !empty($pw)) 
    { 
     $headers = array('Authorization: Basic ' . base64_encode("$user:$pw")); 
     curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
    } 

    $ok = curl_exec($ch); 
    curl_close($ch); 
    $head = ob_get_contents(); 
    ob_end_clean(); 

    $regex = '/Content-Length:\s([0-9].+?)\s/'; 
    $count = preg_match($regex, $head, $matches); 

    return isset($matches[1]) ? $matches[1] : "unknown"; 
} 
?> 
+0

當前腳本的確切問題是什麼? – Baba

回答

0

如果你想只是把文件給用戶,請按照下列步驟操作:

  1. 開始輸出緩衝。
  2. 按原樣讀取文件內容以進行緩衝。
  3. 將響應頭設置爲基於MIME類型(如發佈的代碼中所示)。
  4. 刷新輸出緩衝區。

如果按照瀏覽器標準無法呈現MIME類型,將提示用戶保存該文件。

+0

我知道你的意思是什麼,並在上面的代碼嘗試做到這一點。你有沒有任何示例代碼?謝謝。 –

+0

http://stackoverflow.com/questions/13150692/output-buffering-for-php-file-download – pMan