2010-10-23 4 views
14

Tôi tìm thấy trên Google một số tập lệnh PHP để giới hạn tốc độ tải xuống của tệp, nhưng tệp tải xuống ở tốc độ 10 Mbps hoặc tải xuống ở tốc độ 80 kbps khi tôi đặt nó, sau 5 mb, nó dừng tải xuống .Giới hạn tốc độ tải xuống bằng cách sử dụng PHP

Một số người có thể cho tôi biết nơi tôi có thể tìm thấy tập lệnh giới hạn tốc độ tải xuống PHP tốt không?

Thank you very much

--- Chỉnh sửa ---

Đây là mã:

<?php 
set_time_limit(0); 
// change this value below 
$cs_conn = mysql_connect('localhost', 'root', ''); 
mysql_select_db('shareit', $cs_conn); 

// local file that should be send to the client 
$local_file = $_GET['file']; 
// filename that the user gets as default 
$download_file = $_GET['file']; 

// set the download rate limit (=> 20,5 kb/s) 
$download_rate = 85; 
if(file_exists($local_file) && is_file($local_file)) { 
    // send headers 
    header('Cache-control: private'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Length: '.filesize($local_file)); 
    header('Content-Disposition: filename='.$download_file); 

    // flush content 
    flush();  
    // open file stream 
    $file = fopen($local_file, "r");  
    while(!feof($file)) { 

     // send the current file part to the browser 
     print fread($file, round($download_rate * 1024));  

     // flush the content to the browser 
     flush(); 

     // sleep one second 
     sleep(1);  
    }  

    // close file stream 
    fclose($file);} 
else { 
    die('Error: The file '.$local_file.' does not exist!'); 
} 




if ($dl) { 
} else { 
    header('HTTP/1.0 503 Service Unavailable'); 
    die('Abort, you reached your download limit for this file.'); 
} 
?> 
+0

bạn nên sử dụng 'echo' thay vì' print', nhanh hơn một chút – FluorescentGreen5

+0

Cảm ơn bạn! –

Trả lời

16

Lý do tải về của bạn dừng lại sau khi 5MB là bởi vì phải mất hơn 60 giây để tải xuống 5MB ở mức 80KB/s. Hầu hết các tập lệnh "giới hạn tốc độ" này sử dụng sleep() để tạm dừng một lúc sau khi gửi một đoạn, tiếp tục, gửi một đoạn khác và tạm dừng lại. Nhưng PHP sẽ tự động chấm dứt một tập lệnh nếu nó được chạy trong một phút hoặc lâu hơn. Khi điều đó xảy ra, quá trình tải xuống của bạn sẽ dừng lại.

Bạn có thể sử dụng set_time_limit() để ngăn chặn tập lệnh của bạn bị chấm dứt, nhưng một số máy chủ web sẽ không cho phép bạn thực hiện việc này. Trong trường hợp đó, bạn không may mắn.

+0

Nếu tôi đặt set_time_limit (0); lúc bắt đầu kịch bản của tôi, nó không giới hạn tốc độ: S .. Xem bài gốc cho mã PHP. –

+6

Tôi không thấy cách sử dụng set_time_limit() sẽ ngừng tập lệnh của bạn hạn chế tốc độ tải xuống. Tất cả những gì cần làm là giữ cho tập lệnh hết thời gian chờ. Trái tim của kịch bản lệnh của bạn là hàm sleep(), không liên quan gì đến set_time_limit(). – mellowsoon

+0

Tôi đã sử dụng nguyên nhân set_time_limit sau 60 giây khi dừng tải xuống ... :( –

9

Thứ hai là quá nhiều thời gian, nó sẽ làm cho khách hàng nghĩ rằng máy chủ không phản hồi và kết thúc sớm quá trình tải xuống. Thay đổi sleep(1)-usleep(200):

set_time_limit(0); 

$file = array(); 
$file['name'] = 'file.mp4'; 
$file['size'] = filesize($file['name']); 

header('Content-Type: application/octet-stream'); 
header('Content-Description: file transfer'); 
header('Content-Disposition: attachment; filename="' . $file['name'] . '"'); 
header('Content-Length: '. $file['size']); 

$open = fopen($file['name'], 'rb'); 
while(!feof($open)){ 
    echo fread($open, 256); 
    usleep(200); 
} 
fclose($open); 
0

tôi đã cố gắng bàn tay của tôi tại một lớp tùy chỉnh có thể giúp bạn đối phó với giới hạn tốc độ tải về, bạn có thể thử cách sau?

class Downloader { 
    private $file_path; 
    private $downloadRate; 
    private $file_pointer; 
    private $error_message; 
    private $_tickRate = 4; // Ticks per second. 
    private $_oldMaxExecTime; // saving the old value. 
    function __construct($file_to_download = null) { 
     $this->_tickRate = 4; 
     $this->downloadRate = 1024; // in Kb/s (default: 1Mb/s) 
     $this->file_pointer = 0; // position of current download. 
     $this->setFile($file_to_download); 
    } 
    public function setFile($file) { 
     if (file_exists($file) && is_file($file)) 
      $this->file_path = $file; 
     else 
      throw new Exception("Error finding file ({$this->file_path})."); 
    } 
    public function setRate($kbRate) { 
     $this->downloadRate = $kbRate; 
    } 
    private function sendHeaders() { 
     if (!headers_sent($filename, $linenum)) { 
      header("Content-Type: application/octet-stream"); 
      header("Content-Description: file transfer"); 
      header('Content-Disposition: attachment; filename="' . $this->file_path . '"'); 
      header('Content-Length: '. $this->file_path); 
     } else { 
      throw new Exception("Headers have already been sent. File: {$filename} Line: {$linenum}"); 
     } 
    } 
    public function download() { 
     if (!$this->file_path) { 
      throw new Exception("Error finding file ({$this->file_path})."); 
     } 
     flush();  
     $this->_oldMaxExecTime = ini_get('max_execution_time'); 
     ini_set('max_execution_time', 0); 
     $file = fopen($this->file_path, "r");  
     while(!feof($file)) { 
      print fread($file, ((($this->downloadRate*1024)*1024)/$this->_tickRate);  
      flush(); 
      usleep((1000/$this->_tickRate)); 
     }  
     fclose($file); 
     ini_set('max_execution_time', $this->_oldMaxExecTime); 
     return true; // file downloaded. 
    } 
    } 

Tôi đã lưu trữ tệp dưới dạng gistub ở đây. - https://gist.github.com/3687527

1

Lớp trình tải xuống là tốt nhưng có một vấn đề nếu bạn có hai lượt tải xuống cùng một lúc, bạn sẽ mất giá trị max_execution_time.

Một số ví dụ:

Tải đầu tiên tập tin (size = 1mb; thời gian tải về 100 giây)

Sau một giây tải về tập tin thứ hai (size = 100 mb; dowload time = 10000 giây)

Đầu tiên tải về thiết max_execution_time-0

Second hãy nhớ _oldMaxExecTime là 0

đầu tiên làm wnload cuối và trở về max_execution_time giá trị cũ

Second cuối tải về và trở max_execution time-0

+1

Thansk cho thông tin giá trị đó Kalanj! –

0

Đầu tiên của tất cả max_execution_time là thời gian thực thi tập lệnh của bạn. Ngủ không phải là một phần của nó.

Về giới hạn tốc độ, bạn có thể sử dụng thứ gì đó như một nhóm Token. Tôi đã đặt tất cả mọi thứ vào một thư viện tiện lợi cho bạn: bandwidth-throttle/bandwidth-throttle

use bandwidthThrottle\BandwidthThrottle; 

$in = fopen(__DIR__ . "/resources/video.mpg", "r"); 
$out = fopen("php://output", "w"); 

$throttle = new BandwidthThrottle(); 
$throttle->setRate(100, BandwidthThrottle::KIBIBYTES); // Set limit to 100KiB/s 
$throttle->throttle($out); 

stream_copy_to_stream($in, $out);