2011-08-11 48 views

回答

32

啓用用戶在Windows Azure中下載文件(blob)可以通過4種方式完成;

  • 直接下載 - 將集裝箱的公共讀訪問或全部公共讀取權限訪問和揭露網址給最終用戶。這種方法的缺點顯然是安全的 - 當URL暴露時,你無法控制訪問。也沒有辦法檢測下載,並在下載之前/之後執行代碼。

  • API下載 - 用戶必須運行Windows應用程序,Silverlight的等等。此外 - 應用程序必須包含storeaccount名稱和關鍵 - 這可能危及安全。特別是如果你有幾個客戶使用同一個帳戶(當然他們仍然可以有自己的容器)。

  • 代理下載 - 讓用戶訪問您的服務器上的URL - 然後從Azure中檢索文件,並將其發送給用戶。這樣做的好處是您可以完全控制下載,您可以在下載之前/之後執行代碼,而且您不必公開任何Azure URL /帳戶信息。事實上 - 最終用戶甚至不會看到該文件存儲在Azure中。 你也可以用這種方式覆蓋文件名。缺點是所有流量都會通過您的服務器 - 所以您可能會遇到瓶頸。

  • 傳遞下載(Azure共享訪問簽名) - 創建簽名並將此簽名插入用戶重定向到Azure的URL中。簽名使用戶能夠在有限的時間內訪問文件。這很可能是你最好的選擇。它使得自定義代碼可以在下載之前執行,它將確保用戶的最大下載速度,並且還確保了良好的安全級別。

這是一個代碼片段,它將文件傳輸給用戶,並覆蓋文件名。

//Retrieve filenname from DB (based on fileid (Guid)) 
// *SNIP* 
string filename = "some file name.txt"; 

//IE needs URL encoded filename. Important when there are spaces and other non-ansi chars in filename. 
if (HttpContext.Current.Request.UserAgent != null &&  HttpContext.Current.Request.UserAgent.ToUpper().Contains("MSIE")) 
filename = HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8).Replace("+", " "); 

context.Response.Charset = "UTF-8"; 
//Important to set buffer to false. IIS will download entire blob before passing it on to user if this is not set to false 
context.Response.Buffer = false; 
context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); 
context.Response.AddHeader("Content-Length", "100122334"); //Set the length the file 
context.Response.ContentType = "application/octet-stream"; 
context.Response.Flush(); 

//Use the Azure API to stream the blob to the user instantly. 
// *SNIP* 
fileBlob.DownloadToStream(context.Response.OutputStream); 

更多的看到這個博客帖子:http://blog.degree.no/2012/04/downloading-blobs-from-windows-azure/

+0

謝謝你這個非常詳細的答案。傳遞下載聽起來正是我需要的。一個問題,在你的代碼示例中,你設置了文件的大小,這是否必須完成,因爲我不知道沒有訪問該文件的信息。 – CeejeeB

+0

設置文件大小是沒有必要的。我這樣做是爲了讓用戶(瀏覽器)能夠看到下載進度。如果你沒有設置,下載時瀏覽器會顯示「unknown filesize」等。 –

+0

在選項3-中,首先將文件下載到捲動的本地資源(temp)文件夾,然後將該URL鏈接到最終用戶。這可能嗎?好主意?在選項4中,有一種方法可以將SAS網址從最終用戶隱藏起來,並讓它們保存文件。我在這裏處理的所有文件都是xmls。 – Aravind

0

首先,你可以使用BLOB URI自己的自定義域名:http://blogs.msdn.com/b/avkashchauhan/archive/2011/03/22/using-custom-domain-name-with-windows-azure-storage-instead-of-windows-stroage-name-blob-core-windows-net.aspx

爲例,爲您的解決方案...

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

StorageCredentialsAccountAndKey credentials = new StorageCredentialsAccountAndKey(ConfigurationManager.AppSettings["WindowsAzureStorageAccountName"], ConfigurationManager.AppSettings["WindowsAzureStorageAccountKey"]); 
CloudStorageAccount cloudStorageAccount = new CloudStorageAccount(credentials, true); 

CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainer"); 

// e.g. GUID of currently logged in user 
string fileName = System.Web.Security.Membership.GetUser().ProviderUserKey.ToString(); 

CloudBlob blob = blobContainer.GetBlobReference(fileName); 

byte[] blobArray = blob.DownloadByteArray(); 

Response.ContentType = "text/plain"; 
Response.AddHeader("content-disposition", "attachment; filename=" + "MyText.txt"); 
Response.BinaryWrite(blobArray); 
Response.End(); 
+1

我看到你在說什麼,但依賴在將文件傳遞到客戶端之前,將文件下載到我的服務器。我需要客戶端能夠從Azure服務器直接下載。 – CeejeeB

+0

您需要基於用戶GUID進行某種URL重寫。也許這可以幫助:http://forums.asp.net/t/1574817.aspx/1 –

4

答案是否定的。您需要在blob上設置content-disposition標頭,並且無法在blob存儲中設置該標頭。

+0

謝謝。我這麼認爲,但只是想確定。 – CeejeeB

+6

除了建議的其他解決方法之外,如果您始終需要相同的友好名稱,則可以將其命名爲'http://me.blob.core.windows.net/mycontainer/9BB34783-8F06-466D-AC20-37A03E504E3F/ MyText.txt' – smarx

+2

謝謝@smarx - 這是一個非常簡單和優雅的解決方案 – dmichael

13

2013年11月有現在在Windows Azure Blob存儲的內容處置頭支持。您可以在blob創建時或通過共享訪問簽名來分配標頭。

我修改了我的保存文檔方法,將可選參數作爲友好名稱下載。

public void SaveDocument(Stream documentToSave, string contentType, string containerName, string url, string friendlyName = null) 
{ 
    var container = GetContainer(containerName); 
    container.CreateIfNotExists(); 
    var blob = container.GetBlockBlobReference(url); 
    blob.Properties.ContentType = contentType; 
    if (friendlyName != null) 
     blob.Properties.ContentDisposition = "attachment; filename=" + friendlyName; 
    blob.UploadFromStream(documentToSave); 
} 

更多一點: http://blog.simontimms.com/2013/12/02/content-disposition-comes-to-azure/

+0

謝謝你的更新 – CeejeeB

33

現在可以通過設置內容處置標題上生成共享訪問簽名:

string sasBlobToken = blob.GetSharedAccessSignature(sharedPolicy, new SharedAccessBlobHeaders() 
      { 
       ContentDisposition = "attachment; filename=" + friendlyFileName 
      }); 
    string downloadLink = blob.Uri + sasBlobToken; 
+3

天才,正是我一直在尋找的! – Bern

+0

P L U S O N E正是我需要的 –