Edited at

Azure Storage に REST API でアップロードする

More than 3 years have passed since last update.

下記とにらめっこして Azure Storage に PHP の curl で REST API でファイルをアップロードしてみました。

あらかじめ下記の3つは作成しておいてください。


  • ストレージアカウント

  • ストレージコンテナ

  • ストレージのアクセスキー

アクセスキーは管理ポータルでストレージアカウントを選択した後の画面で、下のほうに項目が現れます。

01-access-key.png

プライマリとセカンダリで2つありますが使うのはどっちでもいいです。恐らくアクセスキーのローテートのために2つ設けられているのでしょう。

02-access-key.png

以下のようなコードで 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);