PHP Conference Japan 2024

stream_context_create

(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)

stream_context_create建立串流上下文

描述

stream_context_create(?array $options = null, ?array $params = null): resource

建立並返回一個串流上下文,其中包含在 options 中提供的任何預設選項。

參數

options

必須是格式為 $arr['wrapper']['option'] = $value 的關聯陣列的關聯陣列,或 null。請參閱上下文選項以取得可用封裝器和選項的清單。

預設為 null

params

必須是格式為 $arr['parameter'] = $value 的關聯陣列,或 null。請參閱 上下文參數以取得標準串流參數的清單。

回傳值

一個串流上下文 resource

變更記錄

版本 描述
8.0.0 optionsparams 現在可為空值。

範例

範例 1 使用 stream_context_create()

<?php
$opts
= [
'http' => [
'method' => "GET",
// 使用換行符號 \n 來分隔多個標頭
'header' => "Accept-language: en\nCookie: foo=bar",
]
];

$context = stream_context_create($opts);

/* 向 www.example.com 發送一個 http 請求
並帶有上面顯示的額外標頭 */
$fp = fopen('http://www.example.com', 'r', false, $context);
fpassthru($fp);
fclose($fp);
?>

參見

新增筆記

使用者貢獻的筆記 11 筆筆記

105
jrubenstein at gmail dot com
17 年前
建立 SSL 串流時(使用 https://)需要記住的一些事項

<?php
$context
= context_create_stream($context_options)
$fp = fopen('https://url', 'r', false, $context);
?>

人們會認為 - 建立串流選項陣列的正確方式如下

<?php
$context_options
= array (
'https' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n"
. "Content-Length: " . strlen($data) . "\r\n",
'content' => $data
)
);
?>

那是錯誤的方式!!!
請注意第 3 行:'https' => array (

正確的方式如下

<?php
$context_options
= array (
'http' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n"
. "Content-Length: " . strlen($data) . "\r\n",
'content' => $data
)
);
?>

請注意,新的第 3 行:'http' => array (

現在 - 請記住這一點 - 我花了幾個小時試圖排除我的問題,當我最終偶然發現這個未記載的問題時。

發佈到安全頁面的完整程式碼如下

<?php
$data
= array ('foo' => 'bar', 'bar' => 'baz');
$data = http_build_query($data);

$context_options = array (
'http' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n"
. "Content-Length: " . strlen($data) . "\r\n",
'content' => $data
)
);

$context = stream_context_create($context_options)
$fp = fopen('https://url', 'r', false, $context);
?>
28
contact (at) thepointsolution.com
14 年前
我有一個重要的注意事項,希望對某些人有幫助。文件中沒有提到的是,當 php 編譯時加入了 --with-curlwrappers,

所以,應該是這樣:

<?php
$opts
= array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);

$context = stream_context_create($opts);
?>

您應該這樣設定標頭:

<?php
$opts
= array(
'http'=>array(
'method'=>"GET",
'header'=>array("Accept-language: en",
"Cookie: foo=bar",
"Custom-Header: value")
)
);

$context = stream_context_create($opts);
?>

這樣才會有效。
8
net_navard at yahoo dot com
18 年前
嗨,您可以建立一個參數陣列(稱為串流上下文),每次您透過 socket 讀取或寫入串流時,都可以傳遞這個陣列。在下面的範例中:

$opts =array('http'=>arra('method'=>"GET",
'header'=>"Accept-language:en\r\n"."Cookie: foo=bar\r\n");

您實際上做的是建立一組參數(要使用的協定、請求方法、額外的 http 標頭和 Cookie),每次您開啟 socket 連線以請求 www.example.com 時都會使用這些參數。如果您想在向 www.example.com 發出請求時,使用這些參數(稱為串流上下文),這樣可以節省大量時間,而不必反覆指定它們。
使用先前的範例,假設您想要建立一個串流上下文,該上下文會傳送一個 "Content-Type" http 標頭,並在向 www.example.com 發出請求時使用它。看看這個:

$opts = array('http'=>array('method'=>"GET",
'header'=>"Content-Type: text/xml; charset=utf-8");

$context = stream_context_create($opts);
$fp = fopen('http://www.example.com','r',false,$context);
fpassthru($fp);
fclose($fp);

現在,當您向 www.example.com 發出請求時,上述 http 標頭將會包含在 socket 中並傳輸到伺服器。祝您好運,朋友,Hossein
19
Ben J
11 年前
我花了整整五個小時才弄清楚這個問題,希望它可以幫其他人節省一些時間。

當您嘗試透過 HTTP proxy 使用 ftp 下載檔案時,請注意以下方式是不夠的:
<?php
$opts
= array('ftp' => array(
'proxy' => 'tcp://vbinprst10:8080',
'request_fulluri'=>true,
'header' => array(
"Proxy-Authorization: Basic $auth"
)
)
);
$context = stream_context_create($opts);
$s = file_get_contents("ftp://anonymous:anonymous@ftp.example.org",false,$context);
?>

您的 proxy 會回應需要驗證。您可能會抓破頭想著「但我已經提供驗證了!」

問題在於 'header' 值只適用於 http 連線。因此,若要在 proxy 上進行驗證,您必須先從 HTTP 提取檔案,該上下文才適用於 FTP。
<?php
$opts
= array('ftp' => array(
'proxy' => 'tcp://vbinprst10:8080',
'request_fulluri'=>true,
'header' => array(
"Proxy-Authorization: Basic $auth"
)
),
'http' => array(
'proxy' => 'tcp://vbinprst10:8080',
'request_fulluri'=>true,
'header' => array(
"Proxy-Authorization: Basic $auth"
)
)
);
$context = stream_context_create($opts);
$s = file_get_contents("http://www.example.com",false,$context);
$s = file_get_contents("ftp://anonymous:anonymous@ftp.example.org",false,$context);
?>

這有點繞遠路,但它有效。請注意,ftp 陣列中的 'header' 值是多餘的,但我還是把它保留下來了。
12
davep at atomicdroplet dot com
17 年前
除了上面提到的上下文選項(附錄 N),在附錄 P 中還可以找到用於 socket 的上下文選項 - https://php.dev.org.tw/manual/en/transports.php
14
louis dot huppenbauer at gmail dot com
12 年前
當使用 https 協定時,您必須確保設定正確的上下文選項,以充分利用 ssl/tls 加密的功能。

<?php
$url
= 'https://secure.example.com/test/1';
$contextOptions = array(
'ssl' => array(
'verify_peer' => true,
'cafile' => __DIR__ . '/cacert.pem',
'verify_depth' => 5,
'CN_match' => 'secure.example.com'
)
);
$sslContext = stream_context_create($contextOptions);
$result = file_get_contents($url, NULL, $sslContext);
?>

關於這些上下文選項的更多資訊,請參考 https://php.dev.org.tw/manual/en/context.ssl.php
5
Andi
9 年前
不要嘗試重複使用 stream_context_create 返回的資源。當使用 https 連線到不同的網域時,似乎無法運作。
17
rlintern at gmail dot com
15 年前
我發現以下程式碼可以讓我將一些二進制數據 POST 到遠端伺服器。我把它放在這裡,因為我無法透過「Google」搜尋或瀏覽此文件找到快速的解決方案。

免責聲明:我不知道這是否是一個「好」的解決方案,因為我是 PHP 的新手,但它可能正好符合您的需求,就像它符合我的需求一樣。我假設使用非常大的檔案會發生不好的事情,因為整個檔案都被讀入 $fileContents 變數中。

我正在使用 PHP 5.2.8。

$fileHandle = fopen("someImage.jpg", "rb");
$fileContents = stream_get_contents($fileHandle);
fclose($fileHandle);

$params = array(
'http' => array
(
'method' => 'POST',
'header'=>"Content-Type: multipart/form-data\r\n",
'content' => $fileContents
)
);
$url = "http://somesite.somecompany.com?someParam=someValue";
$ctx = stream_context_create($params);
$fp = fopen($url, 'rb', false, $ctx);

$response = stream_get_contents($fp);
6
Brian Gottier
15 年前
在某些情況下,根據伺服器配置,將 header 選項設定為陣列,而不是字串。

<?php
$opts
= array(
'http'=> array(
'method'=> "GET",
'header'=> array( "Cookie: foo="bar"l ),
'user_agent'=>
$_SERVER['HTTP_USER_AGENT']
)
);
?>
5
mathieu dot laurent at gmail dot com
15 年前
透過 Proxy 連線

<?php

$opts
= array('http' => array('proxy' => 'tcp://127.0.0.1:8080', 'request_fulluri' => true));
$context = stream_context_create($opts);

$data = file_get_contents('https://php.dev.org.tw', false, $context);

echo
$data;

?>
4
sp0n9e at gmail dot com
17 年前
這裡有一個非常簡單的方法可以輕鬆地執行 POST,而無需使用 cURL 或手動編寫 HTTP 請求,它使用 tcp:// 包裝器。我喜歡使用 contexts,只是因為它們的普遍性,而且不需要像 cURL 這樣的可選函式庫(儘管 cURL 是較受歡迎的函式庫之一)。

<?php

$options
= array(
'http'=>array(
'method'=>"POST",
'header'=>
"Accept-language: en\r\n".
"Content-type: application/x-www-form-urlencoded\r\n",
'content'=>http_build_query(array('foo'=>'bar'))
));

$context = stream_context_create($options);

fopen('http://www.example.com/',false,$context);

?>
To Top