Windows Azure入门教学系列 (七):使用REST API访问Storage Service

 

公告 :本博客为微软云计算中文博客 的镜像博客。 部分文章因为博客兼容性问题 ,会影响阅读体验 。如遇此情况,请访问 原博客

 

 


 

本文是 Windows Azure 入门教学 的第七篇文章。

 

本文将会介绍如何使用 REST  API来直接访问 Storage Service

在前三篇教学中,我们已经学习了使用 Windows Azure SDK所提供的 StorageClient来使用 Blob Storage, Queue Storage以及 Table Storage的基本方法。我们在前几篇教学中也提及最终 StorageClient也是通过发送 REST请求来与服务器端通信的。

在这篇教学中,我们会以 Blob Storage为例,说明如何使用 REST API直接与服务器进行通信。需要说明的是,这篇教学中使用的是 C#语言。但是由于 REST API实际上是通过 HTTP发送的 HTTP消息,使用其他语言的工程师同样可以参考代码逻辑了解如何构造 HTTP消息以便在其他编程语言中使用。

在开始本教学之前,请确保你从 Windows Azure  平台下载 下载并安装了最新的 Windows Azure开发工具。 本教学使用 Visual Studio 2010作为开发工具。

步骤一:准备工作

在本教学中我们将使用 List Blobs API,欲了解详细信息,请参见 List Blobs

API的作用是返回给定的 Container中的 Blob信息。为了测试我们的代码我们首先需要有一个已经创建的 Container并且向其中添加至少一个 Blob。由于如何添加 Container Blob的方法我们已经在 Windows Azure入门教学系列   ( ):使用 Blob Storage 中提过,在此不赘述。读者可以按照 Windows Azure入门教学系列   ( ):使用 Blob Storage 中的代码创建名为 helloworldcontainer Container和名为 myfile Blob (只需注释掉删除 Blob的代码并运行程序即可 )

步骤二:创建解决方案和项目

首先,请确保 Storage Emulator已经启动。我们可以找到管理器的进程手动启动或者让 Visual Studio 2010帮助我们启动他。

右击工具栏中 Windows Azure模拟器的图标,选择” Show Storage Emulator UI”。弹出如下图所示的窗口:

 

 

我们要关注的是 Service management Blob所在的一行。要确保 Status Running

确认完毕后启动 Visual Studio 2010,并且新建一个 Console项目。  

步骤三:添加程序集引用

请在项目属性页里确认项目的 Target framework的值是 .NET Framework 4 .NET Framework 3.5。然后在 Console项目中添加对 System.Web程序集的引用。该程序集安装在 GAC中。在 .NET标签下能够找到该程序集。我们将使用该程序集来发送 HTTP请求和接受 HTTP消息。

步骤四:添加代码

首先在项目中的 Program.cs中引用命名空间:

using   System.IO;

using   System.Collections.Specialized;

using   System.Collections;

using   System.Web;

using   System.Net;

 

然后在 Program.cs中添加如下代码 :

class   Program

{

     internal   class   CanonicalizedString

     {

         private   StringBuilder   canonicalizedString =  new   StringBuilder ();

 

         internal   CanonicalizedString(string   initialElement)

         {

             this .canonicalizedString.Append(initialElement);

         }

 

         internal   void   AppendCanonicalizedElement(string   element)

         {

             this .canonicalizedString.Append("/n" );

             this .canonicalizedString.Append(element);

         }

         internal   string   Value

         {

             get

             {

                 return   this .canonicalizedString.ToString();

             }

         }

     }

 

      const   string   bloburi =  @"http://127.0.0.1:10000/devstoreaccount1" ;

     const   string   accountname =  "devstoreaccount1" ;

     const   string   key =  "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" ;

     const   string   method =  "GET" ;

 

     static   void   Main(string [] args)

     {

         string   AccountName = accountname;

         string   AccountSharedKey = key;

         string   Address = bloburi;

         string   container =  "helloworldcontainer" ;

 

         //  创建请求字符串

         string   QueryString =  "?restype=container&comp=list" ;

         Uri   requesturi =  new   Uri (Address +  "/"   + container + QueryString);

         string   MessageSignature =  "" ;

 

         //   创建 HttpWebRequest

         HttpWebRequest   Request = (HttpWebRequest )HttpWebRequest .Create(requesturi.AbsoluteUri);

         Request.Method = method;

         Request.ContentLength = 0;

         Request.Headers.Add("x-ms-date" ,  DateTime .UtcNow.ToString("R" ));

         Request.Headers.Add("x-ms-version" ,  "2009-09-19" );

 

         //  开始创建签名

          MessageSignature +=  "GET/n" ;  //   Verb

         MessageSignature +=  "/n" ;  // Content-Encoding

         MessageSignature +=  "/n" ;  // Content-Language

         MessageSignature +=  "/n" ;  // Content-Length

         MessageSignature +=  "/n" ;  // Content-MD5

          MessageSignature +=  "/n" ;  // Content-Type

         MessageSignature +=  "/n" ;  // Date

         MessageSignature +=  "/n" ;  // If-Modified-Since

         MessageSignature +=  "/n" ;  // If-Match

         MessageSignature +=  "/n" ;  // If-None-Match

         MessageSignature +=  "/n" ;  // If-Unmodified-Since

         MessageSignature +=  "/n" ;  // Range

 

         // CanonicalizedHeaders

         ArrayList   list =  new   ArrayList ();

         foreach   (string   str  in   Request.Headers.Keys)

         {

             if   (str.ToLowerInvariant().StartsWith("x-ms-" ,  StringComparison .Ordinal))

             {

                 list.Add(str.ToLowerInvariant());

             }

         }

         list.Sort();

         foreach   (string   str2  in   list)

         {

             StringBuilder   builder =  new   StringBuilder (str2);

             string   str3 =  ":" ;

             foreach   (string   str4  in   GetHeaderValues(Request.Headers, str2))

             {

                 string   str5 = str4.Replace("/r/n" ,  string .Empty);

                 builder.Append(str3);

                  builder.Append(str5);

                 str3 =  "," ;

             }

             MessageSignature += builder.ToString() +  "/n" ;

         }

         MessageSignature += GetCanonicalizedResourceVersion2(requesturi, AccountName);

 

         //   开始创建签名

         byte [] SignatureBytes = System.Text.Encoding .UTF8.GetBytes(MessageSignature);

         System.Security.Cryptography.HMACSHA256   SHA256 =  new System.Security.Cryptography.HMACSHA256 (Convert .FromBase64String(AccountSharedKey));

 

         //   创建 Authorization HTTP 消息头的值

         String   AuthorizationHeader =  "SharedKey "   + AccountName +  ":"   +  Convert .ToBase64String(SHA256.ComputeHash(SignatureBytes));

 

         //   把编码后的签名加入到 Authorization HTTP 消息头中

         Request.Headers.Add("Authorization" , AuthorizationHeader);

 

          //   获取返回消息

         using   (HttpWebResponse   response = (HttpWebResponse )Request.GetResponse())

         {

             if   (response.StatusCode ==  HttpStatusCode .OK)

             {

                 //   服务器返回成功消息

                 using   (Stream   stream = response.GetResponseStream())

                 {

                     using   (StreamReader   sr =  new   StreamReader (stream))

                     {

 

                         var   s = sr.ReadToEnd();

                         //   输出返回消息

                          Console .WriteLine(s);

                     }

 

                 }

             }

             else

             {

                 //  这里可以抛出异常信息

             }

         }

         Console .ReadLine();

 

     }

 

     static   ArrayList   GetHeaderValues(NameValueCollection   headers,  string   headerName)

     {

         ArrayList   list =  new   ArrayList ();

         string [] values = headers.GetValues(headerName);

         if   (values !=  null )

         {

             foreach   (string   str  in   values)

             {

                 list.Add(str.TrimStart(new   char [0]));

             }

         }

         return   list;

     }

 

     static   string   GetCanonicalizedResourceVersion2(Uri   address,  string   accountName)

     {

         StringBuilder   builder =  new   StringBuilder ("/" );

         builder.Append(accountName);

         builder.Append(address.AbsolutePath);

         CanonicalizedString   str =  new   CanonicalizedString (builder.ToString());

         NameValueCollection   values =  HttpUtility .ParseQueryString(address.Query);

         NameValueCollection   values2 =  new   NameValueCollection ();

         foreach   (string   str2  in   values.Keys)

         {

             ArrayList   list =  new   ArrayList (values.GetValues(str2));

             list.Sort();

             StringBuilder   builder2 =  new   StringBuilder ();

              foreach   (object   obj2  in   list)

             {

                 if   (builder2.Length > 0)

                 {

                     builder2.Append("," );

                 }

                 builder2.Append(obj2.ToString());

             }

             values2.Add((str2 ==  null ) ? str2 : str2.ToLowerInvariant(), builder2.ToString());

         }

         ArrayList   list2 =  new   ArrayList (values2.AllKeys);

         list2.Sort();

         foreach   (string   str3  in   list2)

         {

             StringBuilder   builder3 =  new   StringBuilder (string .Empty);

             builder3.Append(str3);

             builder3.Append(":" );

             builder3.Append(values2[str3]);

             str.AppendCanonicalizedElement(builder3.ToString());

         }

         return   str.Value;

     }

}

 

步骤五:观察并分析代码

我们首先观察下面三行代码:

const   string   bloburi =  @"http://127.0.0.1:10000/devstoreaccount1" ;

const   string   accountname =  "devstoreaccount1" ;

const   string   key =  "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" ;

 

这三行代码定义了 Blob Storage服务端口,我们使用的账户名和密码。由于使用的是本地模拟的 Storage,所以必须使用固定的端口地址,用户名以及密码。可以参考 Development Storage Windows Azure Storage Services的不同之处 获取更多信息。

在代码中,我们使用 HttpWebRequest  构造并发送 HTTP请求。由于我们的例子中使用的是 List Blobs API我们需要查阅 List Blobs 对该 API的规定构造符合规定的 HTTP请求。

在规定中说明了如果该 container没有被设置为允许匿名访问,那么必须由于账户拥有者调用该 API才能返回结果。要这样做必须添加 Authorization HTTP消息头。我们必须严格按照 Authentication Schemes 规定的格式来生成该 HTTP消息头。

 

步骤六:运行程序

如果一切正常,你将会看到 Console程序输出如下信息,内容为名为 helloworld Container中所有 Blob的信息:

下面列出一部分 Windows Azure 入门系列课程视频 Windows Azure 入门系列课程(1):Windows Azure 概述 http://www.aboutyun.com/thread-5777-1-2.html Windows Azure 入门系列课程(2):Windows Azure Storage 简介 2008年10月27日,在洛杉矶举行的专业开发者大会PDC2008上,前微软首席软件架构师Ray Ozzie宣布了微软的云计算战略以及云计算平台——Windows Azure。The Azure Services Platform (Azure)是一个互联网级的运行于微软数据中心系统上的云计算服务平台,它提供操作系统 Windows Azure 和可以单独或者一起使用的开发者服务。Azure是一种灵活和支持互操作的平台,它可以被用来创建云中运行的应用或者通过基于云的特性来加强现有应用。它开放式的架构给开发者提供了Web应用、互联设备的应用、个人电脑、服务器、或者提供最优在线复杂解决方案的选择。 Windows Azure以云技术为核心,提供了软件+服务的计算方法。 它是Azure服务平台的基础。Azure用于帮助开发者开发可以跨越云端和专业数据中心的下一代应用程序,在PC、Web和手机等各种终端间创造完美的用户体验。 Azure能够将处于云端的开发者个人能力,同微软全球数据中心网络托管的服务,比如存储、计算和网络基础设施服务,紧密结合起来。这样,开发者就可以在“云端”和“客户端”同时部署应用,使得企业与用户都能共享资源。Ray Ozzie说道。“今天,无论对于开发社区还是对于微软来说,都是一个转折点。我们所提出的技术将改变原来的游戏规则,同时为Web开发者和企业开发者带来新的机遇。 微软会保证Azure服务平台自始至终的开放性和互操作性。我们确信企业的经营模式和用户从Web获取信息的体验将会因此改变。最重要的是,这些技术将使我们的用户有能力决定,是将应用程序部署在以云计算为基础的互联网服务上,还是将其部署在客户端,或者根据实际需要将二者结合起来。 Windows Azure 是 Microsoft 为公有云提供的应用程序平台。您可以多种不同方式使用此平台。例如,可以使用 Windows Azure 构建一个在 Microsoft 数据中心运行并存储其数据的 Web 应用程序。或者只使用 Windows Azure 存储数据,而使用此数据的应用程序则在本地(即公有云之外)运行。可以使用 Windows Azure 创建虚拟机以用于开发和测试,或运行 SharePoint 和其他应用程序。可以使用 Windows Azure 构建拥有海量用户的高度可缩放应用程序。因为此平台提供了种类广泛的服务,所以所有这些想法都有可能实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值