How to upload a blob to Azure storage by REST API

Authored by Yang Wang

Microsoft provides quite a few SDKs for Azure storage service, which make it quite easy to access Azure storage programmatically.  But in some special cases, you still need to access Azure storage using REST API. In this article, I will talk about how to use Azure Storage REST API to implement a common user scenario. I will create a container on Azure storage, upload a file and finally delete the file by REST API.  To make it easier, I use PHP to construct the request and test it via Curl.

Prerequisite:

Before you get started, make sure that you have set up your development environment:

  1. An Azure subscription. Try it for free here: https://azure.microsoft.com/en-us/free/
  2. An Azure storage account. Learn how to create a storage account: /en-us/azure/storage/storage-create-storage-account.
  3. PHP developing environment. Learn how to install PHP on Windows system: https://php.net/manual/en/install.windows.php.

Steps:

1. AUTHENTICATION:

When accessing Azure storage by REST API, we should pay attention to the “Authorization” header. Here are the steps on how to construct the authorization header using storage container as an example.
#1. Get date time

   date_default_timezone_set ( 'GMT' );  
   $date = date ( "D, j M Y H:i:s T" );  

#2. Set API version

    $version = "2009-09-19"; 

#3. Construct the string to sign

    $utf8_encode_str = utf8_encode ("PUT\n\n\n0\n\n\n\n\n\n\n\n\nx-ms-date:". $date . "\nx-ms-version:" 
  .$version."\n/yangstorage2/containertest\nrestype:container" ); 

This means creating a container under my account “yangstorage2” with a name “containertest.”

#4. Encode the string using HMAC-SHA256 and Base64 algorithm.

  1.  Get storage account key from Azure portal.
  2. Base64 decode the account key we get in step 1.
  3. Use the decoded string we get in step2 to sign the string we get in #3 by hmac-sha256.
  4. Base64 encode the result in step 3.
    $account_key = "##############"; 
   $key = base64_decode($account_key); 
   $signature_str = base64_encode(hash_hmac('sha256', $utf8_encode_str, $key, true)); 

So, the format of final Authorization header is as follows:
    Authorization: SharedKey <AccountName>:<Signature>
Here Signature is your signature string and the AccountName is the name of the account requesting the resource. For more information about authentication of Azure storage, please see /en-us/rest/api/storageservices/fileservices/authentication-for-the-azure-storage-services#a-namesubheading2a-specifying-the-authorization-header.

2. CREATING A CONTAINER ON AZURE STORAGE 
We need to create a container before uploading file to Azure storage. Here is the steps to create a container using REST APIs:

#1. Follow step1 to generate the authentication signature

    $utf8_encode_str = utf8_encode ("PUT\n\n\n0\n\n\n\n\n\n\n\n\nx-ms-date:". $date . "\nx-ms-version:".$version."\n/yangstorage2/containertest\nrestype:container" ); 
   $signature_str = base64_encode(hash_hmac('sha256',    $utf8_encode_str, base64_decode($account_key), true)); 

#2. Construct the request header.

    $header = array ( 
    "x-ms-date: " . $date, 
    "x-ms-version: " . $version, 
    "Authorization: SharedKey yangstorage2:" . $signature_str, 
    "Content-Length: 0" 
    ); 

#3. Send a Put request to create the container.

    $url=" https://<account name>.blob.core.windows.net/<container name>?restype=container" ; 
   $ch = curl_init (); 
  curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false); 
  curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, 'PUT' ); 
  curl_setopt ($ch, CURLOPT_URL, $url ); 
  curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true ); 
  curl_setopt ($ch, CURLOPT_HTTPHEADER, $header); 
  curl_setopt ($ch, CURLOPT_HEADER, True ); 
  curl_exec ( $ch ); 

Please note: Since I set SSL_VERIFYPEER to false this basically causes cURL to blindly accept any server certificate, without doing any verification as to which CA signed it, and whether or not that CA is trusted. If you’re at all concerned about the data you’re passing to or receiving from the server, you’ll want to enable this peer verification properly. Doing so is a bit more complicated. For more information, see https://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/.
For more information about how to use curl in PHP, see https://php.net/manual/en/book.curl.php.
Following is my output when we run the code:
Request:
PUT https://yangstorage2.blob.core.windows.net/containertest?restype=container
x-ms-date: Fri, 21 Apr 2017 09:29:08 GMT
x-ms-version: 2009-09-19
Content-Length: 0
Authorization: SharedKey    yangstorage2:l8D7zQcOLheM2oJK1u0rPYolmGr18Jxbkw13Rm1uq5w=
Respond:
HTTP/1.1 201 Created
Transfer-Encoding: chunked
Last-Modified: Fri, 21 Apr 2017 09:29:10 GMT
ETag: 0x8D48898DDACB6FB
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: edac1bae-0001-0063-3b81-ba78b3000000
x-ms-version: 2009-09-19
Date: Fri, 21 Apr 2017 09:29:09 GMT
For more information, see /en-us/rest/api/storageservices/fileservices/create-container.

3. UPLOAD A FILE TO AZURE BLOB 

#1. Get file content via built-in function “file_get_contents”

    $fdata = file_get_contents("<file name with full path>"); 

#2. Follow step1 to generate the authentication signature

    $utfStr = "PUT\n\n\n". strlen($fdata) ."\n\ntext/plain; charset=UTF-8\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:" . $date . "\nx-ms-version:" . $version . "\n/yangstorage2/con/" . $blobname ;<br>  $signature_str = base64_encode(hash_hmac('sha256', $utf8_encode_str, base64_decode($account_key), true)); 

#4. Construct the headers

   $header = array (
   "x-ms-blob-type: BlockBlob",
   "x-ms-date: " . $date,
   "x-ms-version: " . $version,
   "Authorization: SharedKey yangstorage2:" . $signature_str,
   "Content-Type: text/plain; charset=UTF-8",
   "Content-Length: " . strlen($fdata),
   );

#5. Send a put request to upload the file data.

   $url =  “https://<account name>.blob.core.windows.net/<container name>/<blob name>”;
  $ch = curl_init ();
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, 'PUT' );
  curl_setopt ( $ch, CURLOPT_URL, $url );
  curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
  curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $fdata);
  curl_setopt ( $ch, CURLOPT_HEADER, True );
  curl_exec ( $ch );

Following is my output when we run the code:
Request
  PUT https://yangstorage2.blob.core.windows.net/containertest/blobtest
 x-ms-blob-type: BlockBlob
  x-ms-date: Mon, 24 Apr 2017 06:31:53 GMT
   x-ms-version: 2014-02-14
  Content-Type: text/plain; charset=UTF-8
  Content-Length: 1461
  Authorization: SharedKey    yangstorage2:kHh+n57Lrg5i0gUHR3PGT9Oamaae8+gqRXal3tLfjVU=
<file data …>
Respond:
 HTTP/1.1 201 Created
  Transfer-Encoding: chunked
  Content-MD5: B64bxG5gdVc/2SD3siYVpQ==
  Last-Modified: Mon, 24 Apr 2017 06:31:55 GMT
  ETag: “0x8D48ADB9A3A75C9”
  Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
  x-ms-request-id: c3dc524d-0001-0030-74c4-bc64bc000000
  x-ms-version: 2014-02-14
  Date: Mon, 24 Apr 2017 06:31:54 GMT
For more information, see /en-us/rest/api/storageservices/fileservices/put-blob.

4. DELETING THE FILE

#1. Follow step1 to generate the authentication signature

    $utfStr = "DELETE\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:" . $date . "\nx-ms-version:" . $version . "\n/yangstorage2/con/" . $blobname ;<br>  $signature_str = base64_encode(hash_hmac('sha256', $utf8_encode_str, base64_decode($account_key), true)); 

#2. Construct the headers

  $header = array (       “x-ms-date: ” . $date,       “x-ms-version: ” . $version,       “Authorization: SharedKey yangstorage2:” . $signature_str,  );

#3. Send a delete request to delete the uploaded file.

    $url="https://<account name>.blob.core.windows.net/<container name>/<blob name><br>";<br>  $ch = curl_init ();<br>  curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false );<br>  curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, 'DELETE' );<br>  curl_setopt ( $ch, CURLOPT_URL, $url );<br>  curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );<br>  curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header);<br>  curl_exec ( $ch ); 

Following is my output when we run the code:
Request:
  DELETE
   https://yangstorage2.blob.core.windows.net/containertest/blobtest
   x-ms-date: Mon, 24 Apr 2017 06:34:09 GMT
   x-ms-version: 2014-02-14
   Authorization: SharedKey     yangstorage2:gbzJzGA5egCa/s8ZR5zVmC5lOFD9AVGFjTZ4dxD5q68=
Respond:
  HTTP/1.1 202 Accepted
  Transfer-Encoding: chunked
  Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
  x-ms-request-id: 8d124a0c-0001-0043-71c4-bc147f000000
  x-ms-version: 2014-02-14
  Date: Mon, 24 Apr 2017 06:34:10 GMT
For more information, see /en-us/rest/api/storageservices/fileservices/delete-blob.

That’s how to use Azure storage service via REST API. As you can see, the point is how to construct the string to sign correctly. Different operation should have the different value of string to sign. I write these samples here to show how to do with it. You can download it from here: https://1drv.ms/u/s!An4UDPFA48_QhQrw5uXNcWpUsVbG
Hope this blog is helpful for you.

Need quick answers to these types of technical scenarios as you are developing your apps on Microsoft Azure or Office 365? Chat directly with a Microsoft support engineer for development tips to quickly resolve programming questions regarding the capability and services of Azure and Office 365. Dev Chat can help you with architecture and design, deployment, implementation and migration scenarios, and much more!