技术开发 频道

实例解读Azure Blob架构及应用开发

    【IT168 技术】Windows Azure Storage 允许云计算应用的开发者在云端存储应用程序数据,为云计算提供耐用、可扩充、具备可用性且有效率的储存服务。Windows Azure Storage通过Development Storage和VS 2008/VS 2010结合使用,为开发者提供了熟悉、友好的程序设计界面。

  Windows Azure Storage由三个重要部分构成:

  Windows Azure Blob:存储大型数据,包括二进制数据和文件。

  Windows Azure Table:存储表数据,类似关系数据库中的数据表,单有所不同,将在后文中介绍。

  Windows Azure Queue:为异步工作提供分派消息服务,有点类似Windows系统的消息队列。

  在某种程度上来说,我们可以把Blob认为是云端的文件系统。在本文中,我们的重点是Windows Azure Blob。通过对Blob架构分析,以一个完整的实例来一步一步介绍如何使用Blob进行开发。

  Blob架构分析

  对Blob架构的分析从两个方面来介绍:Blob应用程序架构和Blob存储结构。
       (1) Blob应用程序架构

  Blob应用程序架构如图1所示: 

 Blob应用程序架构分析

  图1 Blob应用程序架构

  通过图1我们可以看到,Blob存储数据是通过一个简单的层级关系来实现的,每个账户Account下有一个容器,这个容器就是用户定义的一套只有一个属性的Blobs(Blob集合),容器不直接存储数据,每个Blobs包含了多个Blob,这些Blob可以分为Blocks和Pages两类。Blob的存储是采用REST(Representational State Transfer,表象化状态转变)方式来进行的,有关REST可以访问维基百科地址:http://zh.wikipedia.org/zh-cn/REST来了解一下。

  同时在图1中,我们可以看到存储账户的地址、Blob Container的地址、Blob的地址,如一个Blob的实际应用的地址如下:

  http://127.0.0.1:10000/devstoreaccount1/imagefiles/0cd5c5f2-063e-4092-b960-a987c5654dee.png

  那么标示我们使用的Storage是本地存储

  账户:devstoreaccount1

  Blob Container:imagefiles

  Blob文件:0cd5c5f2-063e-4092-b960-a987c5654dee.png

  (2) Blob存储结构

  在本地开发的环境中,我们使用了安装在本地的SQL Express。要想了解Blob的存储结构,首先连接到数据库上看看。

  使用SSMS连接本地的SQL Express数据库,如图1所示:

 Blob应用程序架构分析

图2 连接本地SQL Express

      在这里使用的SQL Express版本是SQL Express 2008,连接上本地SQL Express后,我们可以看到开发环境的存储数据库如图3所示

 这个案例的开发步骤:第一步:创建项目

  图3 开发环境存储表

  由图3中的表我们可以看到,除了账户表(Account),这些表是针对Blob、Queue、Table三种存储服务来设计的,事实上,Blob的存储结构如图4所示:

 这个案例的开发步骤:第一步:创建项目

  图4 Blob的存储结构

  应用与案例

  在本文的案例中,我们将使用Blob存储上传到云端的图片文件,包括对云端的图片文件的列表展示、上传、删除、下载等功能。

  在开始案例之前我们简要说明一下此案例的开发环境:

  VS 2008 / VS 2010

  SQL Express 2005 / SQL Express 2008

  Windows Azure Tools for Microsoft Visual Studio 1.1,其下载的地址是:

  http://www.microsoft.com/downloads/details.aspx?familyid=5664019E-6860-4C33-9843-4EB40B297AB6&displaylang=en

  Windows Azure SDK

  http://www.microsoft.com/downloads/details.aspx?FamilyID=21910585-8693-4185-826e-e658535940aa&displaylang=en

  在本例中,将使用VS 2010来创建项目,下面我们开始介绍这个案例的详细开发步骤:

  第一步:创建项目

  在开始|所有程序里打开Microsoft Visual Studio 2010,创建新的Cloud项目DemoStorageBlob, 如图5所示:

 这个案例的开发步骤:第一步:创建项目图5 创建项目DemoStoragBlob

           输入项目名称DemoStoragBlob,解决方案名称后,点击“确定 OK”,自动打开添加云应用项目界面,如图6所示:

 这个案例的开发步骤:第一步:创建项目

  图6 创建Web Role

     选择Asp.Net Web Role,创建名为BlobWebRole的项目,点击“确定 OK”,我们创建的项目结构最终如图7所示:

 这个案例的开发步骤:第一步:创建项目

图7 DemoStorageBlob项目结构
 

        第二步:添加WebRole程序代码

  在WebRole程序代码设计部分,我们要完成的任务是:设计图片实体类、设计上传显示界面,完成上传、显示、删除功能,可以说是整个案例的核心部分。

  本案例中我们要处理的Blob对象是图片文件,因此,在BlobWebRole项目中,添加一个Image图片的实体类ImageEntity,代码如下:

public class ImageEntity
    {
        
public Uri FileUri { get; set; }
        
public string FileName { get; set; }
        
public long Length { get; set; }
        
public string FolderName { get; set; }
        
public bool IsReadOnly { get; set; }
        
public bool IsExists { get; set; }
        
public string FullFileName { get; set; }
        
public string ExtendName { get; set; }
        
public string CreatorName { get; set; }
        
public DateTime CreateTime { get; set; }
    }

         添加完ImageEntity类的代码后,对Default.Aspx页面进行简单的设计,在Default页面里,有两部分,一部分是上传图片,另一部分是列表显示Blob里的数据,代码如下:

<form id="form1" runat="server">
    
<div>
        
<div><!--上传图片-->
            
<asp:Label ID="lblFilePath" Text="上传文件" AssociatedControlID="fileUploadControl"
                runat
="server" />
            
<asp:FileUpload ID="fileUploadControl" runat="server" />
            
<asp:RequiredFieldValidator ID="filUploadValidator" ControlToValidate="fileUploadControl"
                ValidationGroup
="fileInfoGroup" ErrorMessage="请选择文件!" runat="Server">
            
</asp:RequiredFieldValidator>
            
<br />
            
<asp:Label ID="lblFileName" Text="文件名称:" AssociatedControlID="txtFileName" runat="server" />
            
<asp:TextBox ID="txtFileName" runat="server" />
            
<asp:RequiredFieldValidator ID="fileNameValidator" ControlToValidate="txtFileName"
                ValidationGroup
="fileInfoGroup" ErrorMessage="请输入文件名!" runat="Server">
            
</asp:RequiredFieldValidator>
            
<br />
            
<asp:Label ID="lblCreator" Text="创 建 者:" AssociatedControlID="txtCreator" runat="server" />
            
<asp:TextBox ID="txtCreator" runat="server" />
            
<asp:RequiredFieldValidator ID="submitterValidator" ControlToValidate="txtCreator"
                ValidationGroup
="fileInfoGroup" ErrorMessage="请输入创建者!" runat="Server">
            
</asp:RequiredFieldValidator>
            
<br />
            
<asp:Button ID="btnSave" Text="保存" CausesValidation="true" ValidationGroup="fileInfoGroup"
                runat
="server" OnClick="btnSave_Click" />
            
<br />
            
<br />
            
<asp:Label ID="statusMessage" runat="server" />
        
</div>
        
<div><!--列表显示图片-->
            
<asp:GridView ID="fileView" AutoGenerateColumns="false" DataKeyNames="FileUri" runat="server"
                OnRowCommand
="RowCommandHandler">
                
<Columns>
                    
<asp:ButtonField Text="Delete" CommandName="DeleteItem" />
                    
<asp:HyperLinkField HeaderText="Link" DataTextField="FileName" DataNavigateUrlFields="FileUri" />
                    
<asp:BoundField DataField="CreatorName" HeaderText="Created by" />
                    
<asp:BoundField DataField="FolderName" HeaderText="FolderName" />
                    
<asp:BoundField DataField="IsReadOnly" HeaderText="IsReadOnly" />
                    
<asp:BoundField DataField="IsExists" HeaderText="IsExists" />
                    
<asp:BoundField DataField="FullFileName" HeaderText="FullFileName" />
                    
<asp:BoundField DataField="ExtendName" HeaderText="ExtendName" />
                    
<asp:BoundField DataField="CreateTime" HeaderText="CreateTime" />
                
</Columns>
            
</asp:GridView>
        
</div>
    
</div>
    
</form>

       下面就是本案例中最重要的核心代码了。

  打开defau.aspx.cs文件,添加如下代码:

  添加引用:

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

       添加代码:

private CloudBlobClient _BlobClient = null;
        
private CloudBlobContainer _BlobContainer = null;
        
private const string conContainerAddress = "imagefiles";
        
private const string conConfigStorageSetting = "BlobConnectionString";

        protected void Page_Load(
object sender, EventArgs e)
        {
            
//设置Windows Azure Storage连接
            var storageAccount
= CloudStorageAccount.FromConfigurationSetting(conConfigStorageSetting);
            _BlobClient
= storageAccount.CreateCloudBlobClient();

            
//获取或创建container
            _BlobContainer
= _BlobClient.GetContainerReference(conContainerAddress);
            _BlobContainer.CreateIfNotExist();

            
//设置权限
            var permissions
= new BlobContainerPermissions();
            permissions.PublicAccess
= BlobContainerPublicAccessType.Container;
            _BlobContainer.SetPermissions(permissions);

            
//显示当前列表
            DisplayFileList();

         在这里我们定义了常量conContainerAddress,它表示我们将要创建的Blob Container名称,注意在这里设置的时候一定要全部使用小写字母,如果使用匈牙利命名法,可能会出现错误。

  在这里初始化了Blob信息,主要是设置了Windows Azure Storage连接的账户、Blob Container的名称。

/// <summary>
        
/// 列表
        
/// </summary>
        
private void DisplayFileList()
        {
            var blobs
= _BlobContainer.ListBlobs();
            var filesList
= new List<ImageEntity>();

            
//查询
            foreach (var blobItem in blobs)
            {
                var cloudBlob
= _BlobContainer.GetBlobReference(blobItem.Uri.ToString());
                cloudBlob.FetchAttributes();
                
//实体字段
                filesList.Add(
new ImageEntity()
                {
                    FileUri
= blobItem.Uri,
                    FileName
= cloudBlob.Metadata["FileName"],
                    Length
= long.Parse(cloudBlob.Metadata["Length"]),
                    FolderName
= cloudBlob.Metadata["FileName"],
                    IsReadOnly
= bool.Parse(cloudBlob.Metadata["IsReadOnly"]),
                    IsExists
= bool.Parse(cloudBlob.Metadata["IsExists"]),
                    FullFileName
= cloudBlob.Metadata["FullFileName"],
                    ExtendName
= cloudBlob.Metadata["ExtendName"],
                    CreatorName
= cloudBlob.Metadata["CreatorName"],
                    CreateTime
= DateTime.Parse(cloudBlob.Metadata["CreateTime"])
                });
            }
            
//绑定列表
            fileView.DataSource
= filesList;
            fileView.DataBind();
        }

 

  在这里使用cloudBlob.FetchAttributes()来获取Blob的属性或者元数据,把查询出来的ImageEntity实体结合绑定到GridView上去,这样我们在列表里就能看到有哪些Blob的数据。

/// <summary>
        
/// 上传
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        protected void btnSave_Click(
object sender, EventArgs e)
        {
            
//获取扩展名
            
string extension = System.IO.Path.GetExtension(fileUploadControl.FileName);

            
//创建Blob并且重命名
            var blob
= _BlobContainer.GetBlobReference(Guid.NewGuid().ToString() + extension);
            blob.UploadFromStream(fileUploadControl.FileContent);

            
//设置元数据到Blob
            blob.Metadata[
"FileName"] = txtFileName.Text;
            blob.Metadata[
"Length"] = fileUploadControl.FileContent.Length.ToString();
            DirectoryInfo di
= new DirectoryInfo(string.Format("{0}\\", conContainerAddress));
            blob.Metadata[
"FolderName"] = di.Name;
            FileInfo file
= new FileInfo(fileUploadControl.PostedFile.FileName);
            blob.Metadata[
"IsReadOnly"] = file.IsReadOnly.ToString();
            blob.Metadata[
"IsExists"] = file.Exists.ToString();
            blob.Metadata[
"FullFileName"] = file.FullName;
            blob.Metadata[
"ExtendName"] = file.Extension;//extension
            blob.Metadata[
"CreatorName"] = txtCreator.Text;
            blob.Metadata[
"CreateTime"] = DateTime.Now.ToShortTimeString();

            blob.SetMetadata();

            
//设置属性
            blob.Properties.ContentType
= fileUploadControl.PostedFile.ContentType;
            blob.SetProperties();

            
//显示列表
            DisplayFileList();
            txtFileName.Text
= string.Empty;
            txtCreator.Text
= string.Empty;
            statusMessage.Text
= string.Empty;
        }

 

 在上传方法中,使用了blob.SetMetadata()来设置Blob的元数据,把元数据存到了Blob中,blob.SetProperties()来设置Blob的属性,并“Set”进去。

  protected void RowCommandHandler(object sender, GridViewCommandEventArgs e)
        {
            
//删除
            
if (e.CommandName == "DeleteItem")
            {
                
// 获取索引
                var index
= Convert.ToInt32(e.CommandArgument);
                var blobUri
= fileView.DataKeys[index].Value.ToString();

                
//Get the container
                var blob
= _BlobContainer.GetBlobReference(blobUri);
                blob.DeleteIfExists();
            }
            
//更新列表
            DisplayFileList();
        }

  在点击“删除 Delete”的时候,将删除选中的Blob,调用了blob.DeleteIfExists(),注意在使用Blob对象时,首先要使用Container的GetBlobReference方法来获取到Blob对象。

  第三步:配置应用程序

  配置应用程序有两种方法,一种是直接修改服务定义文件:ServiceDefinition.csdef,服务配置文件ServiceConfiguration.cscfg;另一种是使用UI来直接配置。不管使用哪种方法,其最终的结果是一样的。在这里我们来使用第二种方法,添加配置节BlobConnectionString。

  打开DemoStorageBlob下的Roles文件夹,双击BlobWebRole,打开“设置 Settings”页面,添加BlobConnectionString,如图9所示:

 开发步骤:配置应用程序置运行调试环境

 图9 添加BlobConnectionString

  添加完后,我们的服务定义文件自动发生了修改:

<ConfigurationSettings>
      
<Setting name="BlobConnectionString" />
    
</ConfigurationSettings>
服务配置文件也同样发生了修改
    
<ConfigurationSettings>
      
<Setting name="BlobConnectionString" value="UseDevelopmentStorage=true" />
    
</ConfigurationSettings>

        服务配置文件也同样发生了修改

  第四步:设置运行调试环境

  配置完成后,编译应用程序,保证没有编译错误的情况,我们要进行调试运行程序之前的设置工作,设置工作主要是Development Fabric和Storage,设置项目的启动项和起始页。

  首先需要设置DemoStorageBlob为启动项目,如图10所示:

 开发步骤:配置应用程序置运行调试环境

图10 设置启动项目

  设置完启动项目后,设置BlobWebRole下的Default为起始页。设置完成后,在开始|所有程序| Windows Azure SDK v1.2|打开Development Fabric,确保我们调试时候的模拟器是开着的,在本案例中,要确保Storage的Blob是运行的,界面如图11所示:

 案例的详细开发第五步:调试运行程序

图11 启动development Storage

  第五步:调试运行程序

  这里没有设置断点来调试程序,直接“Run”起来我们的案例,初始化的界面如图12所示:

 案例的详细开发第五步:调试运行程序

  图12 上传初始界面

  选择文件,输入文件名称、创建者,点击上传,上传几个文件后的界面如图13所示:

 案例的详细开发第五步:调试运行程序

  图13 上传4个图片文件到Blob

  图13中已经上传了4个图片文件,点击文件文件名,可以在打开已经上传的图片文件,点击“Delete”,删除文件TestBlob4,界面如图14所示:

 案例的详细开发第五步:调试运行程序

  图14 删除后的界面

  不仅能通过运行的前台页面来查看文件,还可以在VS 2010中通过Server Explorer来查看Blob对象,这也是VS开发平台强大的地方之一,通过VS打开Blob的界面如图15所示:

 案例的详细开发第五步:调试运行程序

  图15 服务器浏览器查看Blob

  在图15所示的界面中,可以输入文件名进行查找,可以打开文件,另存文件到本地。

  我们在页面上做的所有操作的结果都存入到了SQL Express的数据库中,在Blob架构分析中,已经介绍了如何连接SQL Express数据库,连接上数据库后,我们查看一下与Blob相关的几个表里数据,界面如图16所示:

 案例的详细开发第五步:调试运行程序

  图16 查询Blob数据

  总结

  本文介绍了Windows Azure Storage三驾马车之一的Blob,对开发者来说Blob是一个存储大容量二进制文件或文件的“虚拟空间”,同时从应用程序和数据结构两个方面介绍了Blob的结构,并通过图片管理的一个应用案例的讲解,使大家对Blob有一个深入的了解。

0
相关文章