web-dev-qa-db-fra.com

Comment télécharger un fichier vers un navigateur depuis Azure Blob Storage

J'ai déjà réussi à répertorier les fichiers disponibles, mais j'avais besoin de savoir comment transmettre ce fichier au navigateur pour qu'un utilisateur puisse le télécharger sans nécessairement l'enregistrer sur le serveur.

Voici comment obtenir la liste des fichiers

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
stackoverfloweth

Bien que le contenu des objets blob puisse être diffusé via un serveur Web, et jusqu'à l'utilisateur final via un navigateur, cette solution met la charge sur le serveur Web, à la fois cpu et NIC.

Une autre approche consiste à fournir à l'utilisateur final un uri vers le blob souhaité à télécharger, sur lequel il peut cliquer dans le contenu html. par exemple. https://myaccount.blob.core.windows.net/mycontainer/myblob.ext.

Le problème est que le contenu est privé, car un uri tel que celui ci-dessus ne fonctionnera pas à moins d'utiliser des blobs publics. Pour cela, vous pouvez créer une signature d'accès partagé (ou une stratégie stockée sur le serveur), ce qui entraîne ensuite une chaîne de requête hachée ajoutée à l'URI. Ce nouvel uri serait valide pour une durée donnée (10 minutes par exemple).

Voici un petit exemple de création d'un SAS pour un 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;

Notez que l'heure de début est définie sur quelques minutes dans le passé. Il s'agit de faire face à la dérive d'horloge. Voici le tutoriel complet J'ai récupéré/modifié cet exemple de code.

En utilisant l'accès direct aux objets blob, vous contournerez complètement votre instance de rôle VM/Web/instance de site Web (ce qui réduira la charge du serveur) et votre utilisateur final récupérera le contenu blob directement à partir du stockage blob. Vous pouvez toujours utiliser votre application Web pour gérer les autorisations, décider du contenu à fournir, etc. Mais ... cela vous permet de créer un lien direct vers les ressources d'objets blob, plutôt que de les diffuser via votre serveur Web.

49
David Makogon

Une fois que l'utilisateur clique sur un fichier, le serveur répond avec ce

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());

ENORME merci à Dhananjay Kumar pour cette solution

9
stackoverfloweth

Si vous utilisez ASP.NET (core), vous pouvez diffuser le contenu dans le navigateur sans enregistrer le fichier sur le serveur et utiliser FileStreamResult qui est IActionResult serait une solution plus élégante.

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