2014-12-17 16 views
11

Mam następujący scenariusz: Możesz pobrać z naszego serwera kilka plików. Jeśli jesteś "normalnym" użytkownikiem, masz ograniczoną przepustowość, na przykład 500 KB. Jeśli jesteś użytkownikiem premium, nie masz limitu przepustowości i możesz go pobrać tak szybko, jak to tylko możliwe. Ale jak mogę to zrozumieć? W jaki sposób przesłać & co?PHP/Javascript: Jak mogę ograniczyć prędkość pobierania?

+0

Dobre pytanie, potrzebuje dobrej odpowiedzi. – Timtech

+0

możliwy duplikat [Ogranicz prędkość pobierania za pomocą PHP] (http://stackoverflow.com/questions/4002106/limit-download-speed-using-php) –

+0

@OleHaugset Nie to samo pytanie, odpowiedzi tam nie mają zastosowania do tego pytania . – Alfabravo

Odpowiedz

6

Uwaga: może to zrobić z PHP, ale polecam niech sam serwer obsługuje dławienie. Pierwsza część tej odpowiedzi dotyczy tego, jakie są twoje możliwości, jeśli chcesz ograniczyć prędkość pobierania tylko w PHP, ale poniżej znajdziesz kilka linków, na których dowiesz się, jak zarządzać limitami pobierania za pomocą serwera.

Jest to rozszerzenie PECL, które sprawia, że ​​to raczej banalne zadanie, zwany pecl_http, który zawiera funkcję http_throttle. Dokumenty zawierają prosty przykład tego, jak to zrobić. To rozszerzenie zawiera także a HttpResponse class, który nie jest dobrze udokumentowanym bankomatem, ale podejrzewam, że używanie metod setThrottleDelay i setBufferSize powinno dać pożądany wynik (opóźnienie przepustnicy => 0,001, rozmiar bufora 20 == ~ 20Kb/s). Od spojrzeń rzeczy, to powinno działać:

$download = new HttpResponse(); 
$download->setFile('yourFile.ext'); 
$download->setBufferSize(20); 
$download->setThrottleDelay(.001); 
//set headers using either the corresponding methods: 
$download->setContentType('application/octet-stream'); 
//or the setHeader method 
$download->setHeader('Content-Length', filesize('yourFile.ext')); 
$download->send(); 

Jeśli nie może/nie chce zainstalować, że można napisać prostą pętlę, ale:

$file = array(
    'fname' => 'yourFile.ext', 
    'size' => filesize('yourFile.ext') 
); 
header('Content-Type: application/octet-stream'); 
header('Content-Description: file transfer'); 
header(
    sprintf(
     'Content-Disposition: attachment; filename="%s"', 
     $file['fname'] 
    ) 
); 
header('Content-Length: '. $file['size']); 
$open = fopen($file['fname'], "rb"); 
//handle error if (!$fh) 
while($chunk = fread($fh, 2048))//read 2Kb 
{ 
    echo $chunk; 
    usleep(100);//wait 1/10th of a second 
} 

Oczywiście , nie buforuj danych wyjściowych, jeśli to zrobisz :), a najlepiej byłoby dodać także instrukcję set_time_limit(0);. Jeśli plik jest duży, prawdopodobnie Twój skrypt zostanie zabity w połowie pobierania, ponieważ osiąga maksymalny czas wykonania.

Innym (i prawdopodobnie lepsze) rozwiązaniem byłoby, aby ograniczyć prędkość pobierania przez konfigurację serwera:

Ja sam nigdy nie ograniczałem tempa pobierania, ale patrząc na link s, myślę, że to sprawiedliwe, by powiedzieć, że nginx jest najprostszym zdecydowanie:

location ^~ /downloadable/ { 
    limit_rate_after 0m; 
    limit_rate 20k; 
} 

To sprawia, że ​​stopy rzutu krańcowy natychmiast i ustawia go do 20k.Szczegóły można znaleźć pod adresem the nginx wiki.

miarę apache obawia się, że to nie że znacznie trudniejsze, ale będzie to wymagać, aby włączyć moduł ratelimit

LoadModule ratelimit_module modules/mod_ratelimit.so 

Wtedy to prosta sprawa mówienia apache, które pliki powinny być zdławiony:

<IfModule mod_ratelimit.c> 
    <Location /downloadable> 
     SetOutputFilter RATE_LIMIT 
     SetEnv rate-limit 20 
    </Location> 
</IfModule> 
1

Można użyć http_throttle z rozszerzenia pecl_http PHP:

<?php 
// ~ 20 kbyte/s 
# http_throttle(1, 20000); 
# http_throttle(0.5, 10000); 
if (!$premium_user) { 
    http_throttle(0.1, 2000); 
} 
http_send_file('document.pdf'); 
?> 

(. Powyższy oparta jest na przykład z http://php.net/manual/en/function.http-throttle.php)

Jeśli serwer API nie pozwala http_throttle utworzyć dwa odrębne, nieuczciwe adresy URL dla użytkowników premium i non-premium. Aby dowiedzieć się, jak dławić jedną z nich, zapoznaj się z dokumentacją serwera HTTP. Zobacz przykład https://serverfault.com/questions/179646/nginx-throttle-requests-to-prevent-abuse dla przykładu dla Nginx. Ta ostatnia ma tę zaletę, że pozwala na obejście problemów, takich jak pobieranie zostanie zakończone wcześniej z powodu zabicia PHP twojego skryptu.

0

jest to użytkownik biblioteki PHP ziemia bandwidth-throttle/bandwidth-throttle

use bandwidthThrottle\BandwidthThrottle; 

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

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

stream_copy_to_stream($in, $out);