php 使用 Curl 将标头作为数组返回
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10589889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Returning header as array using Curl
提问by StuffandBlah
I'm trying to get the response & the response headers from CURL using PHP, specifically for Content-Disposition: attachment; so I can return the filename passed within the header. This doesn't seem to get returned within curl_getinfo.
我正在尝试使用 PHP 从 CURL 获取响应和响应标头,特别是对于 Content-Disposition:attachment; 所以我可以返回在标题中传递的文件名。这似乎没有在 curl_getinfo 中返回。
I've tried using the HeaderFunction to call a function to read the additional headers, however, I am unable to add the contents to an array.
我已经尝试使用 HeaderFunction 调用一个函数来读取额外的标题,但是,我无法将内容添加到数组中。
Does anyone have any ideas please?
请问有人有什么想法吗?
Below is part of my code which is a Curl wrapper class:
下面是我的代码的一部分,它是一个 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);
}
回答by c.hill
Here, this should do it:
在这里,应该这样做:
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;
}
回答by Markus Knappen Johansson
The anwser from c.hill is great but the code will not handle if the first response is a 301 or 302 - in that case only the first header will be added to the array returned by get_header_from_curl_response().
c.hill 的 anwser 很棒,但是如果第一个响应是 301 或 302,代码将无法处理 - 在这种情况下,只有第一个标头会添加到 get_header_from_curl_response() 返回的数组中。
I've updated the function to return an array with each of the headers.
我已经更新了函数以返回一个包含每个标题的数组。
First I use this lines to create a variable with only the header content
首先,我使用此行创建一个仅包含标题内容的变量
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($a, 0, $header_size);
Than I pass $header in to the new get_headers_from_curl_response()-function:
然后我将 $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;
}
This function will take header like this:
此函数将采用这样的标题:
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
And return an array like this:
并返回一个这样的数组:
(
[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
)
)
回答by Pieter Ennes
Using the array()form for method callbacks should make the original example work:
使用array()方法回调的形式应该使原始示例工作:
curl_setopt($this->_ch, CURLOPT_HEADERFUNCTION, array($this, 'readHeader'));
curl_setopt($this->_ch, CURLOPT_HEADERFUNCTION, array($this, 'readHeader'));
回答by Maxim Belkanov
Another my implementation:
另一个我的实现:
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;
}
Used in case, which request format is:
用于情况,请求格式是:
Host: *
Accept: *
Content-Length: *
and etc ...
主持人:*
接受:*
内容长度:*
等等...
回答by Maxim Belkanov
Simple and straightforward
简单明了
$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];
}
}
回答by Anthony Harley
C.hill's answer is great but breaks when retrieving multiple cookies. Made the change here
C.hill 的回答很好,但在检索多个 cookie 时会中断。在这里进行了更改
public 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;
}
回答by elixon
Fixing issues:
修复问题:
- Error when content of the header contained ': '(split string)
- Multiline-headers were not supported
- Duplicate headers (Set-Cookie) were not supported
- 标题内容包含“:”(拆分字符串)时出错
- 不支持多行标头
- 不支持重复标头 (Set-Cookie)
This is my take on the topic ;-)
这是我对这个话题的看法;-)
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;
}
回答by Pierre-Alexis de Solminihac
You can use http_parse_headersfunction.
您可以使用http_parse_headers函数。
It comes from PECLbut you will find fallbacks in this SO thread.
回答by sun
you can do 2 ways
你可以做 2 种方法
by set curl_setopt($this->_ch, CURLOPT_HEADER, true); header will come out with response message from curl_exec(); you must search keyword 'Content-Disposition:' from response message.
by use this function get_headers($url) right after you call curl_exec(). $url is url called in curl. the return is array of headers. search for 'Content-Disposition' in array to get what you want.
通过 set curl_setopt($this->_ch, CURLOPT_HEADER, true); 标头将与 curl_exec() 的响应消息一起出现;您必须从响应消息中搜索关键字“Content-Disposition:”。
通过在调用 curl_exec() 后立即使用此函数 get_headers($url)。$url 是 curl 中调用的 url。返回是标题数组。在数组中搜索“Content-Disposition”以获得你想要的。

