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).



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

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;

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


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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.