上一篇:Windows Azure(四-5):直接与服务器进行通信
序:由于云端的特殊性,通常情况下,对文件系统的读写建议使用Blob Storage来代替。这就产生了一个问题:对于一个已经写好的本地应用程序,其中使用了NTFS API对本地文件系统读写的代码是否需要进行完全重写以便迁移到Windows Azure平台上呢?答案是否定的。
Windows Azure平台提供了Drive的功能。
怎么做到的呢?
在1.1版本的SDK中提供了CloudDrive类,能够将本地NTFS文件系统Mount(安装)到Blob Storage上。我们只要添加一小段代码来表明我们希望Mount Drive到Blob Storage上就能重用大部分已有的对本地文件系统访问的代码。这样,我们已有的程序能够无缝地迁移到Windows Azure上而不需要做大的改动。
准备工作:
Windows Azure 平台下载并安装了最新的Windows Azure开发工具
实例
删除并重新创建Default.aspx 页面,然后在Default.aspx.cs中引用命名空间:
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.IO;
然后添加下列代码:
public partial class Default : System.Web.UI.Page
{
string _driveLetter = WebRole.DriveLetter;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Bind();
}
}
void Bind()
{
// 显示被Mount的Drive根目录下的所有文件
DirectoryInfo di = new DirectoryInfo(string.Format("{0}\\", _driveLetter));
this.GridView1.DataSource = di.GetFiles();
this.GridView1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
// 在被Mount的Drive根目录下保存文件
if (this.FileUpload1.HasFile)
{
File.WriteAllBytes(string.Format("{0}\\{1}", _driveLetter, this.FileUpload1.FileName), this.FileUpload1.FileBytes);
Bind();
}
}
}
在Default.aspx中添加下列代码:
<form id="form1" runat="server">
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Upload" οnclick="Button1_Click" />
<asp:GridView AllowPaging="true" PageSize="20" ID="GridView1" runat="server">
</asp:GridView>
</form>
接下来在WebRole.cs中引用命名空间:
using Microsoft.WindowsAzure.StorageClient;
然后添加下列代码:
public class WebRole : RoleEntryPoint
{
public static string DriveLetter { get; private set; }
CloudDrive myCloudDrive;
public override bool OnStart()
{
// 当用配置文件中ConfigurationSettings时必须调用CloudStorageAccount.SetConfigurationSettingPublisher
// 来说明当配置文件在发布后被更改时将采取何种操作
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
{
configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
RoleEnvironment.Changed += (sender, arg) =>
{
if(arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
.Any((change) => (change.ConfigurationSettingName == configName)))
{
if(!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
{
RoleEnvironment.RequestRecycle();
}
}
};
});
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
return base.OnStart();
}
public override void Run()
{
CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
LocalResource localCache = RoleEnvironment.GetLocalResource("InstanceDriveCache");
CloudDrive.InitializeCache(localCache.RootPath, localCache.MaximumSizeInMegabytes);
// 检查Container是否存在,不存在则创建
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
blobClient.GetContainerReference("drives").CreateIfNotExist();
// 创建Cloud Drive
myCloudDrive = storageAccount.CreateCloudDrive(
blobClient
.GetContainerReference("drives")
.GetPageBlobReference("mydrive.vhd")
.Uri.ToString()
);
try
{
myCloudDrive.Create(64);
}
catch (CloudDriveException)
{
}
DriveLetter = myCloudDrive.Mount(0, DriveMountOptions.Force);
base.Run();
}
public override void OnStop()
{
myCloudDrive.Unmount();
base.OnStop();
}
}
最后,修改配置文件。在Cloud Service项目的ServiceConfiguration.cscfg中添加下列配置:
<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="WindowsAzureDriveDemonstration"xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="1" osVersion="*">
<Role name="WebRole1">
<Instances count="1" />
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
<Setting name="DataConnectionString" value="UseDevelopmentStorage=true" />
</ConfigurationSettings>
</Role>
</ServiceConfiguration>
在ServiceDefinition.csdef中添加下列配置(注意将Sites部分的内容删除或注释掉):
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="WindowsAzureDriveDemonstration" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole1">
<Sites>
<Sitename="Web">
<Bindings>
<Bindingname="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
<LocalResources>
<LocalStorage name="InstanceDriveCache" cleanOnRoleRecycle="false" sizeInMB="300" />
</LocalResources>
<ConfigurationSettings>
<Setting name="DataConnectionString" />
</ConfigurationSettings>
</WebRole>
</ServiceDefinition>
效果: