學好Windows Azure必看的一本書
圖片來源:http://books.gotop.com.tw/v_ACL036700
首先,如果各位對Windows Azure不是很熟悉的話,我推薦小朱的《Windows Azure Platform應用程式開發教戰手札(第二版)》。
ASP.NET Web API介接服務
「介接服務」的意思是,在Web API裡,我們可以拿別人的服務來成為我的服務,Client只是使用者,他不需要知道細節。以「上傳檔案」而言,當Client上傳一個檔案,你可以儲存在本機,也就是進行File I/O的動作,你可以儲存在Database裡,也就是進行Database I/O動作。
在以下範例中,我們要在Web API裡去儲存檔案至Windows Azure的Blob儲存體中,也就是說,我們拿Windows Azure Storage服務來當成我們服務內容之一。
這裡的概念很重要,例如,我們公司有申請HiCloud服務,在HiCloud的服務內容中有一項HiCloud S3服務,它是一項和Amazon S3一模一樣服務。S3是Simple Storage Service的縮寫,基本上,它也是一項RESTful Service,透過RESTful Service提供“檔案存取”的功能。
也就是說,我們不一定只能選擇Windows Azure Storage,只要對方有提供API給我們存取,我們都可以拿來當成Web API服務的一部分,而Client並不需要知道這些細節。
使用Windows Azure Storage Emulator測試
那天在twMVC#8課程現場並無網路,而我有辦法進行此一範例的Demo要拜謝Windows Azure Storage Emulator,如果各位有安裝Web Tools 2012.2,預設就會安裝Windows Azure SDK,不然就必須到Windows Azure官網去下載安裝(VS 2012 SDK | VS 2010 SDK)。Windows Azure SDK會在本機安裝模擬器(Emulator),讓我們就算在沒有網路的環境,也能進行Windows Azure相關程式碼的測試。
在使用要切換本機與Windows Azure正式環境也非常容易,只需要透過web.config裡的<appSettings>段落去進行組態切換即可。
<!-- 重點一:連線Blob資訊 --> <add key="CloudStorageConnectionString" value="UseDevelopmentStorage=true" /> <!-- <add key="CloudStorageConnectionString" value="DefaultEndpointsProtocol=http;AccountName=NAME;AccountKey=KEY"/> -->
Key名稱可自訂,value是才是重點,使用本機的儲存體模擬器必須指定“UseDevelopmentStorage=true”,當完成開發後,只需要切換組態至Windows Azure的設定,會立即馬上改為Windows Azure Storage服務。
上傳檔案至Blob
一、首先在Models目錄新增一個Files類別,用來儲存檔案資訊:
''' <summary> ''' 儲存上傳檔案資訊 ''' </summary> Public Class FileDetails Property Name As String Property Size As Long Property ContentType As String Property Location As String End Class
二、新增一個Helpers目錄,新增BlobHelper輔助類別,用以幫忙我們快速取得容器資訊。這裡注意的是,必須先將「Microsoft.WindowsAzure.Configuration」與「Microsoft.WindowsAzure.StorageClient」加入參考。
Imports Microsoft.WindowsAzure Imports Microsoft.WindowsAzure.StorageClient ''' <summary> ''' Windows Azure Blob輔助方法 ''' </summary> ''' <remarks></remarks> Public Class BlobHelper ''' <summary> ''' 取得與設定Azure Blob容器 ''' </summary> Public Shared Function GetWebApiContainer() As CloudBlobContainer ' 從appSettings裡的連線字串取得Storage的AccountName Dim storageAccount As CloudStorageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("CloudStorageConnectionString")) ' 建立Blob client Dim blobClient As CloudBlobClient = storageAccount.CreateCloudBlobClient() ' 取得容器(container)的參考 ' 容器名稱必須小寫,請參考:http://msdn.microsoft.com/en-us/library/windowsazure/dd135715.aspx Dim container As CloudBlobContainer = blobClient.GetContainerReference("webapicontainer") ' 確認容器是否存在,不存在就建立一個新容器 container.CreateIfNotExist() ' 啟用公開存取Blob Dim permissions As BlobContainerPermissions = container.GetPermissions() If permissions.PublicAccess = BlobContainerPublicAccessType.Off Then permissions.PublicAccess = BlobContainerPublicAccessType.Blob container.SetPermissions(permissions) End If Return container End Function End Class
三、新增一個Providers目錄,新增一個AzureBlobStorageMultipartProvider類別。
Imports System.Collections.Generic Imports System.IO Imports System.Net.Http Imports System.Threading.Tasks Imports Microsoft.WindowsAzure.StorageClient ''' <summary> ''' 繼承MultipartFileStreamProvider,實作ExecutePostProcessingAsync方法。 ''' </summary> ''' <remarks>http://msdn.microsoft.com/zh-tw/library/system.net.http.multipartfilestreamprovider(v=vs.108).aspx</remarks> Public Class AzureBlobStorageMultipartProvider Inherits MultipartFileStreamProvider Private _container As CloudBlobContainer Public Property Files As List(Of FileDetails) Sub New(container As CloudBlobContainer) ' Path.GetTempPath():回目前使用者的暫存資料夾的路徑。 MyBase.New(Path.GetTempPath()) _container = container Files = New List(Of FileDetails)() End Sub Public Overrides Function ExecutePostProcessingAsync() As Task ' 上傳檔案到Azure Blob儲存體,然後從本機移除它們 ' FileData:http://msdn.microsoft.com/zh-tw/library/system.net.http.multipartfiledata(v=vs.108).aspx For Each Data As MultipartFileData In FileData Dim fileName As String = Path.GetFileName(Data.Headers.ContentDisposition.FileName.Trim("""")) ' 取得加入Blob Dim blob As CloudBlob = _container.GetBlobReference(fileName) ' 指定上傳MediaType blob.Properties.ContentType = Data.Headers.ContentType.MediaType ' 上傳 blob.UploadFile(Data.LocalFileName) ' 刪除本機檔案 File.Delete(Data.LocalFileName) ' 加入Files集合 Files.Add(New FileDetails With { .ContentType = blob.Properties.ContentType, .Location = blob.Uri.AbsoluteUri, .Name = blob.Name, .Size = blob.Properties.Length}) Next Return MyBase.ExecutePostProcessingAsync() End Function End Class
這裡我們繼承MultipartFileStreamProvider類別並覆寫ExecutePostProcessingAsync方法。MultipartFileStreamProvider類別在《ASP.NET MVC 4網站開發美學》第7-124頁 上傳檔案一節我們有進行討論,讀者可以配合著看以加強瞭解。
這裡基本上是使用Windows Azure SDK裡的方法,將上傳的檔案寫入Blob儲存體之中。
四、新增FilesController類別,新增Post方法與Get方法。
Imports System.Collections.Generic Imports System.Net Imports System.Net.Http Imports System.Threading.Tasks Imports System.Web.Http Imports Microsoft.WindowsAzure.StorageClient Public Class FilesController Inherits ApiController ''' <summary> ''' 上傳檔案至Windows Azure Blob儲存體 ''' </summary> Function PostFile() As Task(Of List(Of FileDetails)) ' 確認MIME為form-data(上傳檔案) If Not Request.Content.IsMimeMultipartContent("form-data") Then ' 回傳HTTP 415 狀態碼 Throw New HttpResponseException(HttpStatusCode.UnsupportedMediaType) End If Dim streamProvider = New AzureBlobStorageMultipartProvider(BlobHelper.GetWebApiContainer()) ' ReadAsMultipartAsync:http://msdn.microsoft.com/zh-tw/library/system.net.http.httpcontentmultipartextensions(v=vs.108).aspx ' 讀取 MIME 多組件訊息的所有主體組件,並產生一組 HttpContent 執行個體,使用 streamProvider 執行個體判斷寫入每一個主體組件的內容。 Return Request.Content.ReadAsMultipartAsync(Of AzureBlobStorageMultipartProvider)(streamProvider) _ .ContinueWith(Of List(Of FileDetails))( Function(f) ' 如果Task發生例外就中斷 If f.IsFaulted Then Throw f.Exception End If Dim provider As AzureBlobStorageMultipartProvider = f.Result Return provider.Files End Function) End Function ''' <summary> ''' 由Blob容器取得已上傳的檔案清單 ''' </summary> Iterator Function GetFiles() As IEnumerable(Of FileDetails) Dim container As CloudBlobContainer = BlobHelper.GetWebApiContainer() For Each blob As CloudBlockBlob In container.ListBlobs() Yield New FileDetails With { .ContentType = blob.Properties.ContentType, .Location = blob.Uri.AbsoluteUri, .Name = blob.Name, .Size = blob.Properties.Length} Next End Function End Class
HTTP POST會對應至PostFile方法,HTTP GET會對應至GetFile方法。PostFile方法讀取上傳的檔案並寫入Blob儲存體之中。GetFile方法會讀取容器內的資訊,產出一分清單。
接下來看是要用Postman或Fiddler進行上傳檔案測試即可。
上傳大檔案的額外設定
ASP.NET預設上傳的檔案大小是 4 MB,如果有上傳大檔案的需求,可以在web.config進行組態設置。
<httpRuntime targetFramework="4.5" maxRequestLength ="1048576"/>
重點在maxRequestLength的設置,例如,上面設置允許上傳 1 GB 大小的檔案。
另外,如果是在IIS,可以設置maxAllowedContentLength,例如,下面在IIS端設置允許 2GB 大小的檔案。
<system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="2147483648" /> </requestFiltering> </security> </system.webServer>
這邊注意一下,maxRequestLength的計算單位是kilobytes,maxAllowedContentLength的計算單位是bytes。
沒有留言:
張貼留言
感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。