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

2010-07-30 作者:蒋建华 来源: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所示:

图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有一个深入的了解。

 
 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号