GetBlockBlobReference not giving the folder path details - azure

I am trying to download a block blob from Azure storage explorer. I am able to download all the block blobs that exist in the root directory of my container. I am unable to download blobs that are nested in subfolders inside the container.
CloudBlockBlob blob = container.GetBlockBlobReference(fileName);
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(1);
sasConstraints.Permissions = SharedAccessBlobPermissions.Read;
string sasBlobToken = blob.GetSharedAccessSignature(sasConstraints);
return blob.Uri.AbsoluteUri + sasBlobToken;

I couldn't get the absolute path of blockBlob using GetBlockBlobReference(fileName). The below code solved my issue. I got the listing and then used LINQ to get the blockBlob with the absolute path details.
This post helped as well
do
{
var listingResult = await blobDirectory.ListBlobsSegmentedAsync(useFlatBlobListing, blobListingDetails, maxBlobsPerRequest, continuationToken, null, null);
//The below lined fetched the blockBlob with the correct directory details.
var blockBlob = listingResult.Results.Where(x => x.Uri.AbsolutePath.Contains(fileName)).Count()>0 ? (CloudBlockBlob)listingResult.Results.Where(x=>x.Uri.AbsolutePath.Contains(fileName)).FirstOrDefault():null;
if (blockBlob != null)
{
sasConstraints.SharedAccessExpiryTime = expiryTimeSAS;
sasConstraints.Permissions = SharedAccessBlobPermissions.Read;
string sasBlobToken = blockBlob.GetSharedAccessSignature(sasConstraints);
return blockBlob.Uri.AbsoluteUri + sasBlobToken;
}
continuationToken = listingResult.ContinuationToken;
} while (continuationToken != null);
Correct me if there is any other efficient way of pulling the blob information from a list of directories in a container.

Below Solution helps to access single File Absolute path residing under Directory( or Folder Path).
public static String GetBlobUri(string dirPath, string fileName)
{
//Get a reference to a blob within the container.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("Blob Key");
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("Blob Container");
CloudBlockBlob blockBlob = container.GetBlockBlobReference(dirPath+fileName);
return blockBlob.Uri.AbsoluteUri;
}
Hope this helps someone trying to access Blob File path based on multi level Directory(Level1/Level2/Level3) path.

Just use the ListBlobs mentioned in the answer from Gaurav Mantri to retrieve all files (blobs) within your desired subfolder. Then iterate over it and download it:
var storageAccount = CloudStorageAccount.Parse("yourConnectionString");
var client = storageAccount.CreateCloudBlobClient();
var container = client.GetContainerReference("yourContainer");
var blobs = container.ListBlobs(prefix: "subdirectory1/subdirectory2", useFlatBlobListing: true);
foreach (var blob in blobs)
{
blob.DownloadToFileAsync("yourFilePath");
}

Related

Azure Blob Storage using only the file name, not the entire path

This works exactly as it should. It uses the entire file path to save the blobs in Azure. However, I would like only the file names to be saved directly into the "container" (not the entire hierarchical structure). Is there a good way to do this?
string[] returnedPaths = Open_File_Dialog();
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// container
CloudBlobContainer container = blobClient.GetContainerReference(_jobID);
container.CreateIfNotExists();
foreach (var filePath in returnedPaths)
{
CloudBlockBlob blob = container.GetBlockBlobReference(filePath);
blob.UploadFromFile(filePath);
}
This was all that was needed.
foreach (var filePath in returnedPaths)
{
string fileName = Path.GetFileName(filePath);
CloudBlockBlob blob = container.GetBlockBlobReference(fileName);
blob.UploadFromFile(filePath);
}

Unsure of correct method to list blobs with a SharedAccess Token

I upgraded WindowsAzure.Storage to 4.0.3
I want to output to a webpage a list of blobs in a folder, where clicking on the link downloads the blob. As the blobs are in a secure container each URI needs a shared access signature.
I used to have:
var dir = Container.GetDirectoryReference(folderName);
List<IListBlobItem> blobs = dir.ListBlobs().ToList();
var blobsInFolder = new List<Uri>();
foreach (IListBlobItem listBlobItem in blobs)
{
var blob = Container.GetBlockBlobReference(listBlobItem.Uri.ToString());
string sasBlobToken = blob.GetSharedAccessSignature(_sasConstraints);
blobsInFolder.Add(new Uri(blob.Uri + sasBlobToken));
}
return blobsInFolder;
This no longer works as GetBlockBlobReference no longer accepts a URI but a filename. IListBlobItem does not include the filename.
I could start chopping up the Uri to get the folder and filename
var blob = Container.GetBlockBlobReference(folderName + "/" + Path.GetFileName(listBlobItem.Uri.AbsolutePath));
...but I feel that's going the wrong way (that I shouldn't have to do this?). Can someone point me in the right way please?
Try casting IListBlobItem to CloudBlockBlob
foreach (IListBlobItem listBlobItem in blobs)
{
var blob = (CloudBlockBlob) listBlobItem;
string sasBlobToken = blob.GetSharedAccessSignature(_sasConstraints);
blobsInFolder.Add(new Uri(blob.Uri + sasBlobToken));
}
return blobsInFolder;

Delete "subpath" from Azure Storage

I know Azure doesn't have actual subpaths, but if I have for example container/projectID/iterationNumber/filename.jpg and I delete a project, how can I delete from ProjectID? Is it possible through coding?
I don't want to use the azure application as I am creating a web app.
Thanks in Advance
EDIT:
This is the code provided by Microsoft to target on specific item:
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("mycontainer");
// Retrieve reference to a blob named "myblob.txt".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob.txt");
// Delete the blob.
blockBlob.Delete();
SystemDesignModel
public static SystemDesign returnImageURL(IListBlobItem item)
{
if (item is CloudBlockBlob)
{
var blob = (CloudBlockBlob)item;
return new SystemDesign
{
URL = blob.Uri.ToString(),
};
}
return null;
}
}
As you know, blob storage does not have the concept of subfolders. It has just 2 level hierarchy - container & blobs. So in essence, a subfolder is just a prefix that you attach to blob name. In your example, the actual file you uploaded is filename.jpg but its name from blob storage perspective is projectID/iterationNumber/filename.jpg.
Since there is no concept of subfolder, you just can't delete it like we do on our local computer. However there's a way. Blob storage provides a way to search for blobs starting with a certain blob prefix. So what you have to do is first list all blobs that start with certain prefix (projectID in your case) and then delete the blobs one at a time returned as a result of listing operations.
Take a look at sample code below:
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
var container = storageAccount.CreateCloudBlobClient().GetContainerReference("container");
BlobContinuationToken token = null;
do
{
var listingResult = container.ListBlobsSegmented("blob-prefix (projectID in your case)", true, BlobListingDetails.None, 5000, token, null, null);
token = listingResult.ContinuationToken;
var blobs = listingResult.Results;
foreach (var blob in blobs)
{
(blob as ICloudBlob).DeleteIfExists();
Console.WriteLine(blob.Uri.AbsoluteUri + " deleted.");
}
}
while (token != null);

Unable to download the files which were uploaded to the blob storage

I have created container on azure storage and with code below made it work to upload my files(blobs) in container. Now it says upload was successful however I can't figure out how to reach those files to download it. There is no documentation on the internet about it.
Any help would be appreciated to solve it.
// create Azure Storage
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=bireddy;AccountKey=8OMbjBeJR+SIYaSt0YtBUzivLKPX5ZbsGJeEY9vsX0BPbX3uy9KxOckK7LuLeH3ZbOh+NoEaiEIV/NWvZbFOrA==");
// create a blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// create a container
CloudBlobContainer container = blobClient.GetContainerReference("mycontainer");
// make it public
container.SetPermissions(
new BlobContainerPermissions {
PublicAccess = BlobContainerPublicAccessType.Container
});
// create a block blob
CloudBlockBlob blockBlob = container.GetBlockBlobReference(FileUpload1.FileName);
// upload to Azure Storage
// this has to be changed sometime later
blockBlob.Properties.ContentType = FileUpload1.PostedFile.ContentType;
blockBlob.UploadFromStream(FileUpload1.FileContent);
Grateful to your discussion.
There are a number of options to download your blobs:
Using PowerShell: See the Azure Storage Powershell guide here:
http://azure.microsoft.com/en-us/documentation/articles/storage-powershell-guide-full/
Using Command Line: See the documentation for the AzCopy tool here:
http://aka.ms/azcopy
Using your C# code: There is a guide here, that includes a section on how to download blobs:
http://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-how-to-use-blobs/
Using GUI-based explorers: There are a number of third-party explorers, some of them are listed here:
http://blogs.msdn.com/b/windowsazurestorage/archive/2014/03/11/windows-azure-storage-explorers-2014.aspx
// Parse the connection string and return a reference to the storage account.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
//Create the Blob service client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("mycontainer");
// Retrieve reference to a blob named
CloudBlockBlob blockBlob2 = container.GetBlockBlobReference(document);
//using (var np = File.Open(#"C:\mydocuments\"+ document, FileMode.Create))
// blockBlob2.DownloadToStream(np, null, options, null);
byte[] fileBytes;
using (var fileStream = new MemoryStream())
{
blockBlob2.DownloadToStream(fileStream, null, options, null);
fileBytes = fileStream.ToArray();
}
return fileBytes;

Copy file from URL to Azure BLOB

I have a file at a remote url such as http://www.site.com/docs/doc1.xls and i would like to copy that file onto my BLOB storage account.
I am aware and know of uploading files to a BLOB storage but wasn't sure how this can be done for a file from remote URL.
Try looking at CloudBlockBlob.StartCopyFromBlob that takes a URI if you are using the .NET client library.
string accountName = "accountname";
string accountKey = "key";
string newFileName = "newfile2.png";
string destinationContainer = "destinationcontainer";
string sourceUrl = "http://www.site.com/docs/doc1.xls";
CloudStorageAccount csa = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
CloudBlobClient blobClient = csa.CreateCloudBlobClient();
var blobContainer = blobClient.GetContainerReference(destinationContainer);
blobContainer.CreateIfNotExists();
var newBlockBlob = blobContainer.GetBlockBlobReference(newFileName);
newBlockBlob.StartCopyFromBlob(new Uri(sourceUrl), null, null, null);
Gaurav posted about this when it first came out. Handy, and his post shows how to watch for completion since the operation is Async.

Resources