get_remote_file() mit fsockopen() Dateien mit PHP über HTTP holen | 12. Januar 2007 um 16:31 Uhr / Programming

Eingestellt am 12. Januar 2007 um 16:31 Uhr » Programming

Wenn man mit PHP arbeitet und die Aufgabe hat eine Datei von einem fremden Server zu holen dann gibt es verschiedene Möglichkeiten. Jede hat so ihre Tücken:

  1. curl - wohl am komfortabelsen, haben aber nur wenige Hoster installiert
  2. PEAR::HTTP_Request (und Verwandte) - sehr komfortabel, haben aber die wenigsten installiert
  3. fopen() - da dies ein Sicherheitsrisiko mit sich bringt schalten da sehr viele Hoster die Unterstützung für remote files aus
  4. fsockopen() ist bei allen verfügbar, dafür etwas tückisch zu implementieren

Das sinnvollste ist es also das ganze mit fsockopen() zu implementieren wenn man nicht auf irgendwelche Abhängigkeiten angewiesen sein möchte.

Mit Hilfe der Jungs aus dem SELFHTML-Chat konnte ich das ganze elegant und mit erstaunlich wenig Code hinbekommen:

function get_remote_file($url, $method = "GET", $data = "", $redirect = 10) {
        
    $url = parse_url($url);

    $fp = fsockopen ($url['host'], (!empty($url['port']) ? (int)$url['port'] : 80), $errno, $errstr, 30);
    
    if ($fp) {
        $path = (!empty($url['path']) ? $url['path'] : "/").(!empty($url['query']) ? "?".$url['query'] : "");
        $header = "\r\nHost: ".$url['host'];
        if("post" == strtolower($method)) $header .= "\r\nContent-Length: ".mb_strlen($data);
        
        fputs ($fp, $method." ".$path." HTTP/1.0".$header."\r\n\r\n".("post" == strtolower($method) ? $data : ""));

        if(!feof($fp)) {
             $scheme = fgets($fp);
            list(, $code ) = explode(" ", $scheme);
            $headers = array("Scheme" => $scheme); 
        }
        
        while ( !feof($fp) ) {
            $h = fgets($fp);
            if($h == "\r\n" OR $h == "\n") break;

            list($key, $value) = explode(":", $h, 2);
            $key = strtolower($key);
            $value = trim($value);
            if(isset($headers[$key])) $headers[$key] .= ','.trim($value);
            else $headers[$key] = trim($value); 

            if($code >= 300 AND $code < 400 AND strtolower($key) == "location" AND $redirect > 0)
                return get_remote_file($headers[$key], $method, $data, --$redirect);
        }
        
        $body = "";
        while ( !feof($fp) ) $body .= fgets($fp);
        
        fclose($fp);
    }
    else return (array("error" => array("errno" => $errno, "errstr" => $errstr)));

    return array("headers" => $headers, "body" => $body);
}

[update 2007-05-05] Ich bin drauf gekommen, dass es ja durchaus Header gibt, die öfters als einmal vorkommen. Bisher wurden diese einfach immer wieder überschrieben, ab jetzt werden die Daten, getrennt durch ein Komma, angehängt.

Man ruft die Funktion einfach mit der kompletten URL auf und bekommt dann ein Array aus den HTTP-Headern und den Body der Datei als String zurück.

Gedacht war es vor allem für die, die Pavatare mit Hilfe von PHP in ihre Software implementieren wollen, aber vielleicht hilft es auch anderen.

Die Funktion ist natürlich Public Domain, also für alle frei nutz-, veränder- und kopierbar. Frei im Sinne von Freibier.


Kommentare

Die Kommentare sind für diesen Eintrag geschlossen.