使用Curl将头返回为数组

时间:2012-05-14 19:34:10

标签: php curl

我正在努力获得响应& CURL使用PHP的响应头,特别是Content-Disposition:attachment;所以我可以返回标题中传递的文件名。这似乎没有在curl_getinfo中返回。

我尝试使用HeaderFunction调用函数来读取其他标题,但是,我无法将内容添加到数组中。

有人有任何想法吗?


以下是我的代码的一部分,它是一个Curl包装类:

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

9 个答案:

答案 0 :(得分:62)

在这里,应该这样做:

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

答案 1 :(得分:29)

来自c.hill的anwser很棒,但是如果第一个响应是301或302,则代码将无法处理 - 在这种情况下,只有第一个头将被添加到get_header_from_curl_response()返回的数组中。

我已更新函数以返回包含每个标题的数组。

首先,我使用这一行创建一个只包含标题内容的变量

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

比我将$ header传递给新的get_headers_from_curl_response() - 函数:

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

此功能将采用如下标题:

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

并返回一个这样的数组:

(
    [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
        )

)

答案 2 :(得分:1)

我的另一个实现:

{{1}}

用于以下情况,请求格式为:

  

主持人:*
  接受:*
  内容长度:*
  等等......

答案 3 :(得分:1)

简单明了

$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];
    }
}

答案 4 :(得分:0)

使用array()表单进行方法回调应该使原始示例有效:

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

答案 5 :(得分:0)

C.hill的答案很棒,但在检索多个Cookie时会中断。在这里做了改变

print("Frame,Group,Average Days,Total Units Sold,Total Placements\n");
//$file = fopen("contacts.csv","w");

foreach($groupedByFrame as $frame){
print($frame['frame'].','.$frame['group'].','.round($frame['avg'],3).','.$frame['qty'].','.$frame['placements']."\n");
  //fputcsv($file,explode(',',$frame));
}

//fclose($file);

答案 6 :(得分:0)

修复问题:

  • 标头内容包含':'(分割字符串)
  • 时出错
  • 不支持多行标题
  • 不支持重复的标头(Set-Cookie)

这是我对主题的看法;-)

list($head, $body)=explode("\r\n\r\n", $content, 2);
$headers=parseHeaders($head); 

function parseHeaders($text) {
    $headers=array();

    foreach (explode("\r\n", $text) as $i => $line) {
        // Special HTTP first line
        if (!$i && preg_match('@^HTTP/(?<protocol>[0-9.]+)\s+(?<code>\d+)(?:\s+(?<message>.*))?$@', $line, $match)) {
            $headers['@status']=$line;
            $headers['@code']=$match['code'];
            $headers['@protocol']=$match['protocol'];
            $headers['@message']=$match['message'];
            continue;
        }

        // Multiline header - join with previous
        if ($key && preg_match('/^\s/', $line)) {
            $headers[$key].=' '.trim($line);
            continue;
        }

        list ($key, $value) = explode(': ', $line, 2);
        $key=strtolower($key);
        // Append duplicate headers - namely Set-Cookie header
        $headers[$key]=isset($headers[$key]) ? $headers[$key].' ' : $value;
    }

    return $headers;
}

答案 7 :(得分:-1)

您可以使用 http_parse_headers 功能。

它来自PECL,但您会找到fallbacks in this SO thread

答案 8 :(得分:-3)

你可以做两种方式

  1. 通过set curl_setopt($ this-&gt; _ch,CURLOPT_HEADER,true); 标题将出现来自curl_exec()的响应消息; 您必须从回复消息中搜索关键字“Content-Disposition:”。

  2. 在调用curl_exec()之后立即使用此函数get_headers($ url)。 $ url是curl中调用的url。返回的是标头数组。在数组中搜索“Content-Disposition”以获得您想要的内容。