web-dev-qa-db-de.com

So laden Sie eine Datei aus Azure Blob Storage in den Browser herunter

Ich habe bereits erfolgreich verfügbare Dateien aufgelistet, aber ich musste wissen, wie ich diese Datei an den Browser weitergeben kann, damit ein Benutzer sie herunterladen kann, ohne sie unbedingt auf dem Server zu speichern

So erhalte ich die Liste der Dateien

var azureConnectionString = CloudConfigurationManager.GetSetting("AzureBackupStorageConnectString");
var containerName = ConfigurationManager.AppSettings["FmAzureBackupStorageContainer"];
if (azureConnectionString == null || containerName == null)
    return null;

CloudStorageAccount backupStorageAccount = CloudStorageAccount.Parse(azureConnectionString);
var backupBlobClient = backupStorageAccount.CreateCloudBlobClient();
var container = backupBlobClient.GetContainerReference(containerName); 
var blobs = container.ListBlobs(useFlatBlobListing: true);
var downloads = blobs.Select(blob => blob.Uri.Segments.Last()).ToList();
25

Blob-Inhalte können zwar über einen Webserver und über einen Browser an den Endbenutzer übertragen werden, diese Lösung belastet jedoch den Webserver, sowohl die CPU als auch die Netzwerkkarte.

Ein alternativer Ansatz besteht darin, dem Endbenutzer eine URL für das gewünschte herunterzuladende Blob bereitzustellen, auf die er in den HTML-Inhalt klicken kann. z.B. https://myaccount.blob.core.windows.net/mycontainer/myblob.ext.

Das Problem dabei ist, wenn der Inhalt privat ist, da eine URL wie die oben beschriebene nur mit öffentlichen Blobs funktioniert. Zu diesem Zweck können Sie eine Shared Access-Signatur (oder eine vom Server gespeicherte Richtlinie) erstellen, die dann zu einer gehashten Abfrage führt, die an die URL angehängt wird. Dieser neue Uri ist für eine bestimmte Zeit gültig (z. B. 10 Minuten).

Hier ist ein kleines Beispiel für das Erstellen eines SAS für einen Blob:

var sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5);
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10);
sasConstraints.Permissions = SharedAccessBlobPermissions.Read;

var sasBlobToken = blob.GetSharedAccessSignature(sasConstraints);

return blob.Uri + sasBlobToken;

Beachten Sie, dass die Startzeit auf einige Minuten in der Vergangenheit festgelegt ist. Hier geht es um Clock-Drift. Hier ist das vollständige Tutorial Ich habe dieses Codebeispiel von gepackt/modifiziert.

Wenn Sie den direkten Blob-Zugriff verwenden, umgehen Sie Ihre VM/Web-Rollen-Instanz/Website-Instanz vollständig (wodurch die Serverlast reduziert wird), und der Endbenutzer ruft den Blob-Inhalt direkt aus dem Blob-Speicher ab. Sie können Ihre Web-App weiterhin verwenden, um Berechtigungen zu erteilen, zu entscheiden, welche Inhalte bereitgestellt werden sollen usw. Auf diese Weise können Sie jedoch direkt auf Blob-Ressourcen verweisen, anstatt sie über Ihren Webserver zu streamen.

49
David Makogon

Sobald der Benutzer auf eine Datei klickt, antwortet der Server damit

var blob = container.GetBlobReferenceFromServer(option);

var memStream = new MemoryStream();
blob.DownloadToStream(memStream);

Response.ContentType = blob.Properties.ContentType;
Response.AddHeader("Content-Disposition", "Attachment;filename=" + option);
Response.AddHeader("Content-Length", blob.Properties.Length.ToString());
Response.BinaryWrite(memStream.ToArray());

Vielen Dank an Dhananjay Kumar für diese Lösung

9

Wenn Sie ASP.NET (Core) verwenden, können Sie den Inhalt in den Browser streamen, ohne die Datei auf dem Server zu speichern. Die elegantere Lösung wäre die Verwendung von FileStreamResult (IActionResult).

var stream = await blob.OpenReadAsync();
return File(stream, blob.Properties.ContentType, option);
3
Andy