下記とにらめっこして Azure Storage に PHP の curl で REST API でファイルをアップロードしてみました。
あらかじめ下記の3つは作成しておいてください。
- ストレージアカウント
- ストレージコンテナ
- ストレージのアクセスキー
アクセスキーは管理ポータルでストレージアカウントを選択した後の画面で、下のほうに項目が現れます。
プライマリとセカンダリで2つありますが使うのはどっちでもいいです。恐らくアクセスキーのローテートのために2つ設けられているのでしょう。
以下のようなコードで REST API でアップロードできます。
- Date のタイムゾーンは +0000 だとダメ
-
\DateTime::RFC2822
とか"r"
とかだとダメ
-
-
x-ms-*
のヘッダーはコロンの後にスペースがあるとダメ - ストレージアクセスキーは Base64 エンコードされている
- 署名で使うときにはデコードが必要
- HMAC は SHA256 です
- CanonicalizedResource にはストレージアカウント名も含みます
- URL のパスとは一致しない
<?php
// ストレージアカウント
$account = 'YOUR_STORAGE_ACCOUNT';
// ストレージコンテナ
$container = 'YOUR_STORAGE_CONTAINER';
// ストレージのアクセスキー
$accessKey = 'YOUR_STORAGE_ACCESS_KEY';
$filename = 'sample.txt';
$body = 'php with curl';
$type = 'text/plain';
$headers = [
'x-ms-blob-type:BlockBlob',
'x-ms-version:2014-02-14',
];
$date = gmdate('D, d M Y H:i:s T');
$size = strlen($body);
$stringToSign = [
// VERB
'PUT',
// Content-Encoding
'',
// Content-Language
'',
// Content-Length
$size,
// Content-MD5
'',
// Content-Type
$type,
// Date
$date,
// If-Modified-Since
'',
// If-Match
'',
// If-None-Match
'',
// If-Unmodified-Since
'',
// Range
'',
];
$stringToSign = array_merge($stringToSign, $headers, ["/$account/$container/$filename"]);
$stringToSign = implode("\n", $stringToSign);
$signature = base64_encode(hash_hmac('sha256', $stringToSign, base64_decode($accessKey), true));
$authorization = "SharedKey $account:$signature";
$headers = array_merge($headers, [
"Authorization:$authorization",
"Date:$date",
"Content-Type:$type",
"Content-Length:$size",
]);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://$account.blob.core.windows.net/$container/$filename",
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $body,
]);
curl_exec($ch);