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

简介: 本文是Windows Azure入门教学的第七篇文章。 本文将会介绍如何使用REST API来直接访问Storage Service。 在前三篇教学中,我们已经学习了使用Windows Azure SDK所提供的StorageClient来使用Blob Storage, Queue Storage以及Table Storage的基本方法。

本文是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中引用命名空间:

双击代码全选
1
2
3
4
5
6
7
8
9
using System.IO;
 
using System.Collections.Specialized;
 
using System.Collections;
 
using System.Web;
 
using System.Net;

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

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
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 += "GETn"; // 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("rn", 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 = newSystem.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;
 
     }
 
}

步骤五:观察并分析代码

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

双击代码全选
1
2
3
4
5
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的信息:

目录
相关文章
|
28天前
|
安全 Windows
【Azure Cloud Service】在Windows系统中抓取网络包 ( 不需要另外安全抓包工具)
通常,在生产环境中,为了保证系统环境的安全和纯粹,是不建议安装其它软件或排查工具(如果可以安装,也是需要走审批流程)。 本文将介绍一种,不用安装Wireshark / tcpdump 等工具,使用Windows系统自带的 netsh trace 命令来获取网络包的步骤
67 32
|
1月前
|
C# Windows
【Azure App Service】在App Service for Windows上验证能占用的内存最大值
根据以上测验,当使用App Service内存没有达到预期的值,且应用异常日志出现OutOfMemory时,就需要检查Platform的设置是否位64bit。
43 11
|
2月前
|
存储 NoSQL MongoDB
MongoDB入门级别教程全(Windows版,保姆级教程)
一份全面的MongoDB入门级教程,包括在Windows系统上安装MongoDB、使用MongoDB Shell和Compass GUI进行数据库操作,以及MongoDB的基本数据类型和查询技巧。
83 2
MongoDB入门级别教程全(Windows版,保姆级教程)
|
4月前
|
安全 API 网络安全
【Azure API 管理】APIM不能连接到 App Service (APIM cannot connect to APP service)
【Azure API 管理】APIM不能连接到 App Service (APIM cannot connect to APP service)
|
4月前
|
Java 应用服务中间件 开发工具
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
|
4月前
|
Java 应用服务中间件 Windows
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
|
4月前
|
数据库 Windows
超详细步骤解析:从零开始,手把手教你使用 Visual Studio 打造你的第一个 Windows Forms 应用程序,菜鸟也能轻松上手的编程入门指南来了!
【8月更文挑战第31天】创建你的第一个Windows Forms (WinForms) 应用程序是一个激动人心的过程,尤其适合编程新手。本指南将带你逐步完成一个简单WinForms 应用的开发。首先,在Visual Studio 中创建一个“Windows Forms App (.NET)”项目,命名为“我的第一个WinForms 应用”。接着,在空白窗体中添加一个按钮和一个标签控件,并设置按钮文本为“点击我”。然后,为按钮添加点击事件处理程序`button1_Click`,实现点击按钮后更新标签文本为“你好,你刚刚点击了按钮!”。
324 0
|
4月前
|
开发者 iOS开发 C#
Uno Platform 入门超详细指南:从零开始教你打造兼容 Web、Windows、iOS 和 Android 的跨平台应用,轻松掌握 XAML 与 C# 开发技巧,快速上手示例代码助你迈出第一步
【8月更文挑战第31天】Uno Platform 是一个基于 Microsoft .NET 的开源框架,支持使用 C# 和 XAML 构建跨平台应用,适用于 Web(WebAssembly)、Windows、Linux、macOS、iOS 和 Android。它允许开发者共享几乎全部的业务逻辑和 UI 代码,同时保持原生性能。选择 Uno Platform 可以统一开发体验,减少代码重复,降低开发成本。安装时需先配置好 Visual Studio 或 Visual Studio for Mac,并通过 NuGet 或官网下载工具包。
407 0
|
4月前
|
Kubernetes Cloud Native 开发者
探索云原生技术:Kubernetes入门与实践探索Windows操作系统的隐藏功能
【8月更文挑战第31天】在数字化转型的浪潮中,云原生技术成为企业提升敏捷性、效率和可靠性的关键。本文将带你了解云原生的核心组件之一——Kubernetes(K8s),通过浅显易懂的语言和实际代码示例,引导你步入这一强大工具的世界。无论你是初学者还是有经验的开发者,本篇都将为你打开一扇通向高效资源管理与自动化部署的大门。
|
4月前
|
网络安全 API 数据安全/隐私保护
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
下一篇
DataWorks