云计算 频道

Azure实战:实例解读如何操作Blob存储

  【IT168微软云计算博客征文专稿】本文介绍如何创建、查询和删除Blob数据,所使用的数据来自Queue的消息数据。

  首先在 Default.aspx 中增加Blob相关的成员变量:

public const string BLOB_CONTAINER_NAME = "blobcontainerpayload";
    
private static BlobStorage _blobStorage = null;
    
private static BlobContainer _blobContainer = null;
    
const int UPDATE_TIMEOUT_SEC = 5;
    
const string SUFFIX = "xml";

    然后再给 _Initialization 处理程序增加初始化代码:

    private void _Initialization()
    {
    
if (_initialized)
    {
    return;
    }
    lock (_syncObj)
    {
    try
    {
    _blobStorage
=
    BlobStorage.Create(StorageAccountInfo
    .GetDefaultBlobStorageAccountFromConfiguration());
    _blobContainer
= _blobStorage.GetBlobContainer(BLOB_CONTAINER_NAME);
    
// 让容器公开,以便我们可以使用REST API从Web通过URI查询Blob
    _blobContainer.CreateContainer(
new NameValueCollection(),
    ContainerAccessControl.Public);
    _queueStorage
=
    QueueStorage.Create(StorageAccountInfo
    .GetDefaultQueueStorageAccountFromConfiguration());
    _queueStorage.RetryPolicy
=
    RetryPolicies.RetryN(
3, TimeSpan.FromSeconds(5));
    MessageQueue queue
= _queueStorage.GetQueue(BLOB_PAYLOAD_QUEUE_NAME);
    queue.CreateQueue();
    queue.MessageReceived
+=
    
new MessageReceivedEventHandler(_OnMessageReceive);
    queue.PollInterval
= 500; // 单位毫秒
    queue.StartReceiving();
// 开始投票
    }
    catch (WebException ex)
    {
    throw
new WebException(
    
string.Format(
    
"---{0}:_Initialization, Windows Azure failed to instatiate storage
    using current account information. Exception caught : {1}",
    this.ToString(),
    ex.Message
    )
    );
    }
    _initialized
= true;
    }
    }

  

  ContainerAccessControl 应该被设置为 Public ,以便应用程序可以使用REST API查询Blob数据,为了改变访问范围,这里提供了两个 CreateContainer() 方法,第一个通过传递一个Blob容器名实例化Blob容器对象,第二个仅仅是调用Blob容器类的一个函数,它必须通过传递一个枚举值 ContainerAccessControl.Public 使用有效的Blob容器实例,这个调用不是必需的,不会覆盖实例本身,但可以修改访问范围。

  调用 _Initialization() 后,Blob存储和Blob容器都已实例化,可以使用Blob容器实例创建一个Blob记录,如:

private void _OnMessageReceive(object sender, EventArgs args)

  {

  Message message
= (args as MessageReceivedEventArgs).Message;

  System.Diagnostics.Trace.WriteLine(

  
string.Format(

  
"--- {0}:_OnMessageReceive, message = <{1}>",

  this.ToString(),

  message.ContentAsString()

  )

  );

  
string blobName = string.Format("{0}{1}", message.Id, SUFFIX);

  
if (!_blobContainer.DoesBlobExist(blobName))

  {

  BlobProperties properties
= new BlobProperties(blobName);

  
// 创建与Blob关联的元数据

  NameValueCollection metadata
= new NameValueCollection();

  metadata[
"MediaID"] = message.Id;

  properties.Metadata
= metadata;

  properties.ContentType
= "text/xml";

  
// 创建Blob

  
byte[] buffer =

  UTF8Encoding.UTF8

  .GetBytes(message.ContentAsString().Replace(
"\r\n", string.Empty));

  MemoryStream ms
= new MemoryStream(buffer);

  BlobContents mediaBlob
= new BlobContents(ms);

  _blobContainer.CreateBlob(properties, mediaBlob,
true);

  }

  _DataBind();

  }

 

  在这个例子中,Blob存储的名字是在接收到Queue消息时创建的,而Blob名是Blob创建时指定的,Blob名可以是任意的,但最好不要包括账号名,因为账号名在部署到Azure云时是可以通过配置文件修改的。

  Azure提供了一个名叫服务总线的服务,为了让Blob存储适应.NET服务总线,建议构思Blob名时多花点心思,下面就是我的一些心得体会:

  · 使用.NET命名空间约定构思Blob名

  · 基于Blob的逻辑或关系结构以分层思想构思Blob名

  当 BlobProperties 对象实例化后,Azure Blob存储的元数据就构造好了,元数据对象是嵌入在 BlobProperties. 的对象实例中的,元数据是Blob存储的属性集,元数据是名称/值对的格式,元数据的真实类叫做 NameValueCollection, ,在这个类实例化之前,命名空间 System.Collections.Specialized 必须包括进来。

  Blob容器在创建Blob存储时会用到两个参数: BlobContents 和 BlobProperties. 。第一个参数容纳了信息的主体,第二个参数容纳了信息的属性,只有 Strea m(流)和 Byte array (字节数组)数据类型可以用于这两个参数,信息主体在实例化成 BlobContents 对象之前,必须转换成这两个数据类型。我们在消息队列事件处理程序中创建Blob对象:

  图1显示了运行时的 Default.aspx 页面。 

 

 

Azure实战:实例解读如何操作Blob存储

 

  图 1 Blob创建结果页面

  图2显示了在 SQL Server Management Studio 中,从 DevelopmentStorageDb 查询 Accounts , AcctBlobContainerMap , BlobContainer 和Blob表的结果。

 Azure实战:实例解读如何操作Blob存储

 

 图 2 Blob存储记录创建后的查询结果

  

  为了检索存储在Blob中的信息, BlobContainer 类提供了一套访问函数查询Blob容器中的Blob或特定Blob的属性,下面是从Blob检索信息的一般步骤。

  1、首先创建一个C#容器类 MediaInfo ,它有三个属性: BlobName , MediaUri 和 MediaID ,这三个属性用来容纳Blob记录的信息。

    public class MediaInfo
    {
    
public MediaInfo(string blobName,
    
string mediaAddress,
    
string mediaID)
    {
    BlobName
= blobName;
    MediaUri
= mediaAddress;
    MediaID
= mediaID;
    }
    
public string MediaUri{get; set;}
    
public string BlobName { get; set; }
    
public string MediaID { get; set; }
    }
    
private void _DataBind()
    {
    IEnumerable
<object> blobs = _blobContainer.ListBlobs(string.Empty, false);
    List
<MediaInfo> mediaList= new List<MediaInfo>();
    foreach (
object blob in blobs)
    {
    
if ((blob as BlobProperties )!= null)
    {
    BlobProperties blobProperties
=
    _blobContainer.GetBlobProperties((blob
as BlobProperties).Name);
    NameValueCollection mediaEntryProperties
= blobProperties.Metadata;
    mediaList.Add(
    
new MediaInfo(
    blobProperties.Name,
    (blob
as BlobProperties).Uri.ToString(),
    mediaEntryProperties[
"MediaID"]
    )
    );
    }
    }
    BlobLinksView.DataSource
= filesList;
    BlobLinksView.DataBind();
}

 

  2、在 Default.aspx 中定义一个 GridView 显示Blob记录。

    <asp:GridView
    id
="BlobLinksView"
    DataKeyNames
="BlobName"
    AllowPaging
="False"
    AutoGenerateColumns
="False"
    GridLines
="Vertical"
    Runat
="server"
    onrowcommand
="RowCommandHandler"
    BackColor
="#B3F2FD" ForeColor="Black"
    BorderColor
="#0066FF" BorderStyle="None" BorderWidth="1px" CellPadding="4"
    Font
-Size="Small" Width="394px">
    
<Columns>
    
<asp:ButtonField Text="Delete" CommandName="DeleteEntry"/>
    
<asp:HyperLinkField
    HeaderText
="Blob ID"
    DataTextField
="MediaID"
    DataNavigateUrlFields
="MediaUri" />
    
</Columns>
    
<RowStyle BackColor="#F7F7DE" />
    
<FooterStyle BackColor="#CCCC99" />
    
<PagerStyle BackColor="#F7F7DE" ForeColor="Black" HorizontalAlign="Right" />
    
<SelectedRowStyle BackColor="#CE5D5A" Font-Bold="True" ForeColor="White" />
    
<HeaderStyle BackColor="#6B696B" Font-Bold="True" ForeColor="White" />
    
<AlternatingRowStyle BackColor="White" />
    
</asp:GridView>
    protected void RowCommandHandler(
object sender, GridViewCommandEventArgs e)
    {
    try
    {
    
if (e.CommandName == "DeleteEntry")
    {
    
int index = Convert.ToInt32(e.CommandArgument);
    
string blobName = (string)BlobLinksView.DataKeys[index].Value;
    
if (_blobContainer.DoesBlobExist(blobName))
    {
    _blobContainer.DeleteBlob(blobName);
    }
    }
    }
    catch { }
    _DataBind();
    }

 

  GridView的列与 MediaInfo 的属性一一对应,如 DataTextField 与 MediaID 属性对应, DataNavigateUrlFields 与 MediaUri 属性对应。

  3、使用 _blobContainer 实例调用 ListBlobs() ,传递两个参数: prefix (在这里是空字符串)和 boolean 标志,这个函数应该返回一个 IEnumerable 类型的实例。

  4、遍历Blob记录集,用 List 类型填充 mediaList 实例本地集合。

  5、将 mediaList 作为 GridView 的 DataSource (数据源),调用 DataBind() 方法将数据绑定到 GridView ,根据设计,调用 ListBlobs() 必须先于调用 GetBlobProperties() ,否则调用 GetBlobProperties() 将总是返回一个null对象。

  如果要删除Blob,需要传递Blob名,为了获得Blob名,我们需要在 Default.aspx 的 GridView 中插入一个原始命令处理程序,并链接到一个按钮,点击相应的视图项目时,为了检索特定的Blob项目ID,在处理程序 RowCommandHandler 后应该插入下面的代码:

  ListBlobs() 检索Blob记录外,也可以使用支持REST查询的工具或应用程序进行检索,如 Fiddler ,它可以产生 HTTP GET/POST/UPDATE 请求。

    protected void RowCommandHandler(object sender, GridViewCommandEventArgs e)
    {
    try
    {
    
if (e.CommandName == "DeleteEntry")
    {
    
int index = Convert.ToInt32(e.CommandArgument);
    
string blobName = (string)BlobLinksView.DataKeys[index].Value;
    
if (_blobContainer.DoesBlobExist(blobName))
    {
    _blobContainer.DeleteBlob(blobName);
    }
    }
    }
    catch { }
    _DataBind();
    }

除了使用 ListBlobs() 检索Blob记录外,也可以使用支持REST查询的工具或应用程序进行检索,如 Fiddler ,它可以产生 HTTP GET/POST/UPDATE 请求。

  图3显示了使用 Fiddler 2. 执行REST查询的查询结果。

 

Azure实战:实例解读如何操作Blob存储

  图 3 使用 Fiddler 2 HTTP 调试工具对Blob数据执行REST查询的查询结果

  查询字符串的语法示例如下:

  http://127.0.0.1:10000/devstoreaccount1/blobpayload/caa95517-3414-4bc2-8f16-0a44a6f156e1xml

  成功的REST查询,返回代码是200。

0
相关文章