2012-05-14 7 views
21

Ich versuche, die Antwort & die Response-Header von CURL mit PHP zu bekommen, die speziell für Content-Disposition: attachment; so kann ich den innerhalb der Kopfzeile übergebenen Dateinamen zurückgeben. Dies scheint nicht in curl_getinfo zurückgegeben zu werden.Return-Header als Array Locken mit

Ich habe versucht, die HeaderFunction mit einer Funktion aufrufe, um die zusätzlichen Header zu lesen, aber ich bin nicht in der Lage, den Inhalt zu einem Array hinzuzufügen.

Hat jemand irgendwelche Ideen bitte?


Unten Teil meiner Code, der eine Curl-Wrapper-Klasse ist:

... 
curl_setopt($this->_ch, CURLOPT_URL, $this->_url); 
curl_setopt($this->_ch, CURLOPT_HEADER, false); 
curl_setopt($this->_ch, CURLOPT_POST, 1); 
curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $this->_postData); 
curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($this->_ch, CURLOPT_USERAGENT, $this->_userAgent); 
curl_setopt($this->_ch, CURLOPT_HEADERFUNCTION, 'readHeader'); 

$this->_response = curl_exec($this->_ch); 
$info = curl_getinfo($this->_ch); 
... 


function readHeader($ch, $header) 
{ 
     array_push($this->_headers, $header); 
} 
+0

Ich sollte hinzufügen, dass readHeader-Funktion Teil der Curl Wrapper-Klasse ist. Die Verwendung von '$ this-> readHeader' funktioniert nicht. – StuffandBlah

+2

Laut den Dokumenten muss Ihre 'readHeader' -Funktion die Anzahl der geschriebenen Bytes zurückgeben. Das Hinzufügen von 'return strlen ($ header)' sollte das funktionieren lassen – marcfrodi

Antwort

52

Hier, das sollte es tun:

curl_setopt($this->_ch, CURLOPT_URL, $this->_url); 
curl_setopt($this->_ch, CURLOPT_HEADER, 1); 
curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, 1); 

$response = curl_exec($this->_ch); 
$info = curl_getinfo($this->_ch); 

$headers = get_headers_from_curl_response($response); 

function get_headers_from_curl_response($response) 
{ 
    $headers = array(); 

    $header_text = substr($response, 0, strpos($response, "\r\n\r\n")); 

    foreach (explode("\r\n", $header_text) as $i => $line) 
     if ($i === 0) 
      $headers['http_code'] = $line; 
     else 
     { 
      list ($key, $value) = explode(': ', $line); 

      $headers[$key] = $value; 
     } 

    return $headers; 
} 
+0

Das macht den Trick. Vielen Dank! – StuffandBlah

+4

Header-Namen sind case insensitive, so ist es wahrscheinlich besser, Case $ Schlüssel zu senken. Außerdem können Multiple-Header den gleichen Namen haben/ – ruz

-3

Sie 2 Möglichkeiten tun können

  1. durch gesetzt curl_setopt ($ this -> _ ch, CURLOPT_HEADER, tru e); Header wird mit Antwortnachricht von curl_exec() kommen; Sie müssen das Stichwort 'Content-Disposition:' aus der Antwortnachricht suchen.

  2. durch die Verwendung dieser Funktion get_headers ($ url) direkt nach curl_exec() aufrufen. $ url ist URL in curl aufgerufen. Die Rückgabe ist ein Array von Headern. Suche nach "Content-Disposition" im Array, um zu bekommen, was du willst.

+2

Die Verwendung von get_headers() würde den Server unnötigerweise mit einer zweiten HTTP-Anfrage laden und könnte sehr wohl einen völlig anderen Satz von Headern ergeben. –

0

Mit dem array() Formulars Methode Rückrufe sollten das ursprüngliche Beispiel Arbeit machen:

curl_setopt($this->_ch, CURLOPT_HEADERFUNCTION, array($this, 'readHeader'));

26

Die anwser von c.hill ist groß, aber der Code wird nicht behandeln, wenn die erste Antwort a 301 oder 302 - in diesem Fall wird nur der erste Header zum Array hinzugefügt, das von get_header_from_curl_response() zurückgegeben wird.

Ich habe die Funktion aktualisiert mit jedem der Header ein Feld zurückzukehren.

Zuerst verwende ich diese Zeilen mit eine Variable zu erstellen, die nur den Inhalt des Headers

$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 
$header = substr($a, 0, $header_size); 

als ich $ header in die neue get_headers_from_curl_response() übergeben - Funktion:

static function get_headers_from_curl_response($headerContent) 
{ 

    $headers = array(); 

    // Split the string on every "double" new line. 
    $arrRequests = explode("\r\n\r\n", $headerContent); 

    // Loop of response headers. The "count() -1" is to 
    //avoid an empty row for the extra line break before the body of the response. 
    for ($index = 0; $index < count($arrRequests) -1; $index++) { 

     foreach (explode("\r\n", $arrRequests[$index]) as $i => $line) 
     { 
      if ($i === 0) 
       $headers[$index]['http_code'] = $line; 
      else 
      { 
       list ($key, $value) = explode(': ', $line); 
       $headers[$index][$key] = $value; 
      } 
     } 
    } 

    return $headers; 
} 

Diese Funktion Header wie folgt nehmen:

HTTP/1.1 302 Found 
Cache-Control: no-cache 
Pragma: no-cache 
Content-Type: text/html; charset=utf-8 
Expires: -1 
Location: http://www.website.com/ 
Server: Microsoft-IIS/7.5 
X-AspNet-Version: 4.0.30319 
Date: Sun, 08 Sep 2013 10:51:39 GMT 
Connection: close 
Content-Length: 16313 

HTTP/1.1 200 OK 
Cache-Control: private 
Content-Type: text/html; charset=utf-8 
Server: Microsoft-IIS/7.5 
X-AspNet-Version: 4.0.30319 
Date: Sun, 08 Sep 2013 10:51:39 GMT 
Connection: close 
Content-Length: 15519 

und ein Array wie folgt zurück:

(
    [0] => Array 
     (
      [http_code] => HTTP/1.1 302 Found 
      [Cache-Control] => no-cache 
      [Pragma] => no-cache 
      [Content-Type] => text/html; charset=utf-8 
      [Expires] => -1 
      [Location] => http://www.website.com/ 
      [Server] => Microsoft-IIS/7.5 
      [X-AspNet-Version] => 4.0.30319 
      [Date] => Sun, 08 Sep 2013 10:51:39 GMT 
      [Connection] => close 
      [Content-Length] => 16313 
     ) 

    [1] => Array 
     (
      [http_code] => HTTP/1.1 200 OK 
      [Cache-Control] => private 
      [Content-Type] => text/html; charset=utf-8 
      [Server] => Microsoft-IIS/7.5 
      [X-AspNet-Version] => 4.0.30319 
      [Date] => Sun, 08 Sep 2013 10:51:39 GMT 
      [Connection] => close 
      [Content-Length] => 15519 
     ) 

) 
+1

Das hat für mich funktioniert. –

-1

Sie können http_parse_headers Funktion verwenden.

Es kommt von PECL aber Sie werden fallbacks in this SO thread finden.

+1

Vielleicht ein bisschen irreführend zu sagen, dass dies "Standard" ist - es ist keine Standard-Erweiterung, z. wird nicht mit PHP ausgeliefert und hat keinen offiziellen Windows-Build. Es ist auch immer noch "0.x", was bedeutet, dass es instabil ist. Ich würde nicht davon abhängen, bis es mindestens als stabil gekennzeichnet ist, und vorzugsweise offiziell als eine Standard-PHP-Erweiterung gebündelt. –

+0

@ mindplay.dk Sie haben recht: aus PECL zu kommen, macht es nicht zum Standard. Wie auch immer, pecl_http ist seit 2006 als stable seit der Version 1.0.0 gekennzeichnet, die letzte stabile Version ist die Version 3.1.0. Ich habe meine Antwort umformuliert, um sie klarer zu machen. –

0

Eine weitere meine Implementierung:

function getHeaders($response){ 

    if (!preg_match_all('/([A-Za-z\-]{1,})\:(.*)\\r/', $response, $matches) 
      || !isset($matches[1], $matches[2])){ 
     return false; 
    } 

    $headers = []; 

    foreach ($matches[1] as $index => $key){ 
     $headers[$key] = $matches[2][$index]; 
    } 

    return $headers; 
} 

falls verwendet, die Anfrage-Format ist:

Host: *
Accept: *
Content-Length: *
und etc. ..

1

Einfach und straig htforward

$headers = []; 
// Get the response body as string 
$response = curl_exec($curl); 
// Get the response headers as string 
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); 
// Get the substring of the headers and explode as an array by \r\n 
// Each element of the array will be a string `Header-Key: Header-Value` 
// Retrieve this two parts with a simple regex `/(.*?): (.*)/` 
foreach(explode("\r\n", trim(substr($response, 0, $headerSize))) as $row) { 
    if(preg_match('/(.*?): (.*)/', $row, $matches)) { 
     $headers[$matches[1]] = $matches[2]; 
    } 
}