Czy file_get_contents () ma ustawienie limitu czasu?

152

Wzywam serię linków przy użyciu file_get_contents()metody w pętli. Przetworzenie każdego łącza może zająć więcej niż 15 minut. Teraz martwię się, czy PHP file_get_contents()ma limit czasu?

Jeśli tak, wygaśnie połączenie i przejdzie do następnego łącza. Nie chcę wywoływać następnego łącza bez zakończenia poprzedniego.

Więc proszę powiedz mi, czy file_get_contents()ma limit czasu. Plik zawierający element file_get_contents()jest ustawiony set_time_limit()na zero (nieograniczony).

Flora Clinton
źródło
Doświadczyłem tego samego zachowania (przekroczenie limitu czasu podczas odpytywania adresu URL na tym samym „serwerze”) w projekcie Visual Studio PHP, który używa narzędzi PHP Tools for Visual Studio. Więcej informacji tutaj .
Uwe Keim
Dzieje się tak również w przypadku korzystania z wbudowanego serwera PHP do wysyłania zapytań dotyczących adresu URL w tej samej witrynie , ponieważ jest to jednowątkowy serwer WWW.
Uwe Keim

Odpowiedzi:

298

Domyślny limit czasu jest definiowany przez default_socket_timeoutustawienie ini , które wynosi 60 sekund. Możesz także zmienić to w locie:

ini_set('default_socket_timeout', 900); // 900 Seconds = 15 Minutes

Innym sposobem, aby ustawić limit czasu, byłoby użyć stream_context_create, aby ustawić limit czasu jako opcji kontekstowych HTTP na owijki strumienia HTTP w użyciu:

$ctx = stream_context_create(array('http'=>
    array(
        'timeout' => 1200,  //1200 Seconds is 20 Minutes
    )
));

echo file_get_contents('http://example.com/', false, $ctx);
gulasz
źródło
8
Czy możesz podać informacje o tym, jak ustawić limit czasu dla adresu URL https?
Vinay,
11
ta rzecz nie działa idealnie, jeśli twoja wartość to 1200, to faktycznie jest to 2400. Po prostu to testuję.
TomSawyer
15
default_socket_timeout, stream_set_timeout i stream_context_create timeout to cały limit czasu dla każdego wiersza odczytu / zapisu, a nie cały limit czasu połączenia.
majsterkowanie
32

Jak wspomniano w @diyism, „ default_socket_timeout, stream_set_timeout i stream_context_create timeout to cały limit czasu dla każdego wiersza odczytu / zapisu, a nie całego limitu czasu połączenia. ” A najlepsza odpowiedź @stewe mnie zawiodła.

Zamiast używać file_get_contents, zawsze możesz użyćcurl z limitem czasu.

Oto działający kod, który działa do wywoływania linków.

$url='http://example.com/';
$ch=curl_init();
$timeout=5;

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);

$result=curl_exec($ch);
curl_close($ch);
echo $result;
Randell
źródło
1
Ta odpowiedź daje inne podejście do kontrolowania limitu czasu połączenia (używając fsockopenzamiast curl): stackoverflow.com/a/3690321/1869825
stevo
2
w curl należy ustawić zarówno CURLOPT_CONNECTTIMEOUT, jak i CURLOPT_TIMEOUT. Zobacz stackoverflow.com/a/27776164/1863432
bhelm
2
To nie jest poprawna odpowiedź, pytanie dotyczy „file_get_contents”. Odpowiedź jest świetna, ale nieodpowiednia.
e-info128
8

Tak! Przekazując kontekst strumienia w trzecim parametrze:

Tutaj z limitem czasu wynoszącym 1 s :

file_get_contents("https://abcedef.com", 0, stream_context_create(["http"=>["timeout"=>1]]));

Źródło w sekcji komentarzy na https://www.php.net/manual/en/function.file-get-contents.php

Opcje kontekstu HTTP :

method
header
user_agent
content
request_fulluri
follow_location
max_redirects
protocol_version
timeout

Inne konteksty: https://www.php.net/manual/en/context.php

NVRM
źródło
1
Odpowiedź z 286 przedstawicielami nie zadziałała, ale twoja :)
VE7JRO
Limit czasu podany w stream_context_createdziała tylko dla limitu czasu połączenia. Jeśli serwer odpowie (wysyła pewne dane) w określonym czasie, ale wysłanie reszty ładunku trwa wiecznie, ten limit czasu nie przerywa powolnego przesyłania.
z80crew
6

Warto zauważyć, że jeśli zmieniasz default_socket_timeout w locie, przydatne może być przywrócenie jego wartości po wywołaniu file_get_contents :

$default_socket_timeout = ini_get('default_socket_timeout');
....
ini_set('default_socket_timeout', 10);
file_get_contents($url);
...
ini_set('default_socket_timeout', $default_socket_timeout);
Pascal Roget
źródło
1
ale wiesz, że ini_set nie ustawia tych rzeczy na stałe, prawda? więc w zasadzie 4 połowa twojego skryptu jest po prostu bezużyteczna
Flash Thunder
2
@FlashThunder Nie, jeśli w dalszej części kodu występuje inne wywołanie file_get_contents, które wymaga poprzedniego limitu czasu. Przywracanie ustawień zmienionych w locie dla określonego bitu kodu po wykonaniu tego kodu jest ogólnie dobrą praktyką.
Leigh Bicknell
1
@FlashThunder dobrą praktyką jest przywrócenie wartości socket_timeout po wywołaniu, aby kolejne wywołania tej samej funkcji w tym samym wykonaniu skryptu korzystały z ustawień globalnych.
Pascal Roget
1

Dla mnie działa, kiedy zmieniam php.ini na moim hoście:

; Default timeout for socket based streams (seconds)
default_socket_timeout = 300
Maks
źródło