公共下载Azure blob时的友好文件名

时间:2011-08-11 14:28:40

标签: azure azure-storage azure-storage-blobs

是否可以保存名称为GUID(或其他任何内容)的blob,但当用户请求文件URI http://me.blob.core.windows.net/mycontainer/9BB34783-8F06-466D-AC20-37A03E504E3F时,下载的内容为友好名称,例如: MyText.txt?

6 个答案:

答案 0 :(得分:50)

现在可以通过在生成共享访问签名时设置content-disposition标头:

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

答案 1 :(得分:37)

允许用户在Windows Azure中下载文件(blob)可以通过4种方式完成;

  • 直接下载 - 将容器的访问权限设置为公共读取访问权限或完全公开读取权限,并将URL公开给最终用户。这种方法的缺点显然是安全性 - 在暴露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/

答案 2 :(得分:16)

截至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/

答案 3 :(得分:4)

答案是否定的。您需要在blob上设置content-disposition标头,并且无法在blob存储中设置该标头。

答案 4 :(得分: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();

答案 5 :(得分:0)

我尝试通过代码和手动设置ContentDisposition属性。而且它对我没有用。我调整了一些东西,它开始起作用。 这可能很奇怪,但是在回传过程中缺少content-disposition标头,直到在blob上传期间将文件名添加到两个Properties and Metadata中为止。

NuGet软件包:WindowsAzure.Storage(版本= 9.3.3)
存储帐户类型:StorageV2(通用v2)

        var cloudStorageAccount = CloudStorageAccount.Parse(chatStorageConnectionString);
        var cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
        string extension = ".jpg";
        string containerName = "foobar";

        var container = cloudBlobClient.GetContainerReference(containerName);

        if(!(await container.ExistsAsync()))
        {
            logger.LogError($"Unable to connect to container {containerName: containerName}");
            return "";
        }

        var imageBlob = container.GetBlockBlobReference(Guid.NewGuid().ToString() + extension);

        // These two lines are what I'm talking about
        imageBlob.Metadata.Add("ContentDisposition", "attachment; filename=\"testfire.jpg\"");
        imageBlob.Properties.ContentDisposition = "attachment; filename=\"testfire.jpg\"";

        await imageBlob.UploadFromStreamAsync(stream);
        if(!await imageBlob.ExistsAsync())
        {
            logger.LogError("Image was not uploaded succesfully.");
            return "";
        }