使用 Azure Blob 存储客户端库 v12 for .NET 下载 blob

6
我正在使用Azure.Storage.Blobs版本12.4.1。我有一个REST端点,想要使用它从存储帐户下载blob。
我需要将结果流式传输到HttpResponseMessage中,并且不想使用MemoryStream。我想直接将结果流式传输到调用客户端。有没有方法可以实现这一点?如何在HttpResponseMessage内容中获取下载的blob?由于会有大量的下载请求,我不想使用MemoryStream。
BlobClient类有一个DownloadToAsync方法,但它需要一个Stream作为参数。
        var result = new HttpResponseMessage(HttpStatusCode.OK);

        var blobClient = container.GetBlobClient(blobPath);
        if (await blobClient.ExistsAsync())
        {
            var blobProperties = await blobClient.GetPropertiesAsync();

            var fileFromStorage = new BlobResponse()
            {                    
                ContentType = blobProperties.Value.ContentType,
                ContentMd5 = blobProperties.Value.ContentHash.ToString(),
                Status = Status.Ok,
                StatusText = "File retrieved from blob"
            };

            await blobClient.DownloadToAsync(/*what to put here*/);
            return fileFromStorage;
        }

我目前正在使用Azure.Storage.Blobs v12.11.0,BlobClient具有OpenRead和OpenReadAsync方法,您可以使用它们。此外,您的代码正在使用像CreateCloudBlobClient这样的方法,这是针对Legacy Azure SDK for .NET的。如果有人使用最新的Azure SDK for .NET和较新版本的Azure.Storage.Blobs v12,则我将提供更更新的解决方案。 - kimbaudi
4个回答

10

您可以创建一个新的内存流,并将 Blob 的内容下载到该流中。

像这样:

You could simply create a new memory stream and download the blob's content to that stream.

        var connectionString = "UseDevelopmentStorage=true";
        var blobClient = new BlockBlobClient(connectionString, "test", "test.txt");
        var ms = new MemoryStream();
        await blobClient.DownloadToAsync(ms);

ms将具有该Blob的内容。在使用之前不要忘记将内存流的位置重置为0


1
我想避免使用MemoryStream,我不想在内存中保存blob内容。 - Angela
其他选项是使用DownloadAsync方法,该方法返回一个BlobDownloadInfo。您可以直接将该对象传递给客户端。 - Gaurav Mantri
3
v12版的替代DownloadTextAsync方法是什么?那是一种非常有用的方法,可以加载存储在Blob存储中的模板。 - dinotom
嗨,@dinotom,你找到了DownloadTextAsync的替代品吗? - Smit
我理解,正确的替换方法是使用DownloadToAsync方法,在该方法中我们可以获取MemoryStream,然后可以基于内存流创建一个StreamReader并利用ReadToEndAsync方法。 - Smit
显示剩余2条评论

1

你需要使用

 BlobDownloadInfo download = await blobClient.DownloadAsync();

download.Content 是二进制流。您可以使用它直接复制到其他流中。

using (var fileStream = File.OpenWrite(@"C:\data\blob.bin"))
{
    await download.CopyToAsync(fileStream);
}

1
我认为这已经不再是一个选项了:https://learn.microsoft.com/en-us/dotnet/api/azure.storage.blobs.models.blobdownloadinfo?view=azure-dotnet - Todd Ropog

0

使用 Azure.Storage.Blobs v12.11.0 下载 blob,我们可以使用 OpenReadAsyncOpenRead

string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING")!;
var serviceClient = new BlobServiceClient(connectionString);
var container = serviceClient.GetBlobContainerClient("myblobcontainername");

string blobName; // the name of the blob
var client = container.GetBlobClient(HttpUtility.UrlDecode(blobName));
var properties = (await client.GetPropertiesAsync()).Value;
Response.Headers.Add("Content-Disposition", $"attachment; filename={Path.GetFileName(client.Name)}");
Response.Headers.Add("Content-Length", $"{properties.ContentLength}");
return File(await client.OpenReadAsync(), properties.ContentType);

-1

尝试使用以下代码将 Blob 下载到 HttpResponseMessage 中。

try
{
    var storageAccount = CloudStorageAccount.Parse("{connection string}");
    var blobClient = storageAccount.CreateCloudBlobClient();
    var Blob = await blobClient.GetBlobReferenceFromServerAsync(new Uri("https://{storageaccount}.blob.core.windows.net/{mycontainer}/{blobname.txt}"));
    var isExist = await Blob.ExistsAsync();
    if (!isExist) {
        return Request.CreateErrorResponse(HttpStatusCode.NotFound, "file not found");
    }
    HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.OK);
    Stream blobStream = await Blob.OpenReadAsync();
    message.Content = new StreamContent(blobStream);
    message.Content.Headers.ContentLength = Blob.Properties.Length;
    message.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(Blob.Properties.ContentType);
    message.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
    {
        FileName = "{blobname.txt}",
        Size = Blob.Properties.Length
    };
    return message;
}
catch (Exception ex)
{
    return new HttpResponseMessage
    {
        StatusCode = HttpStatusCode.InternalServerError,
        Content = new StringContent(ex.Message)
    };
}

这是我以前用的,但现在我需要使用Azure.Storage.Blobs version=12.4.1和没有OpenReadAsync的BlobClient。 - Angela
同样的问题。如果这反映了最新的Azure.Storage.Blogs库,那就太好了,它目前是v12。 - FlyingMaverick
Azure.Storage.Blobs v12.11.0有OpenReadAsyncOpenRead,因此看起来微软将其重新引入了。 - kimbaudi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接