Download a file from Azure blob storage - c#

I am writing a service that uploads / downloads files to and from Azure blob storage. I have the upload part working fine. I've been reading how to download the files and there seems to be several ways of doing it.
I've managed to download the file as a stream which works fine but I read somewhere that it's possible to simply pass the absolute URI of the file and get the browser to download the file.
I'm not sure how to do this. Do I send the URI to the request output stream? Any advice or examples of doing this appreciated. I'm using C# but we have other clients usng this service (such as Angular).

You need to create endpoint (GET) to obtain public URL as described in Azure Docs and either:
Return it to client who then can invoke GET on returned URI
Return HTTP REDIRECT response with redirection to Blob's public Url
Third option, if you just need client to have this file is to pass streams, so create endpoint returning stream, read Blob to memory stream, and return memorystream to client. Then you don't need to mess with authentication and anonymous access.

Downloading the source file:
public static Stream DownloadFile(string blobName)
{
CloudBlobContainer container = GetContainer();
CloudBlob blob = container.GetBlobReference(blobName);
MemoryStream memoryStream = new MemoryStream();
blob.DownloadToStream(memoryStream);
memoryStream.Position = 0;
return memoryStream;
}
Setting up and returning container:
private static CloudBlobContainer GetContainer()
{
string accountName = "***";
string accountKey = "***";
string endpoint = $"https://{accountName}.blob.core.windows.net/";
string containerName = "***";
StorageCredentials storageCredentials = new StorageCredentials(accountName, accountKey);
CloudStorageAccount cloudStorageAccount = new CloudStorageAccount(
storageCredentials, new Uri(endpoint), null, null, null);
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer container = cloudBlobClient.GetContainerReference(containerName);
container.CreateIfNotExists();
return container;
}

Related

GetPropertiesAsync on BlobBaseClient does not return from the server

I'm trying to create a seekable blob read stream for reading zip entry from my blob storage
and for that I want to know what is the length of the content, and for that I need to call
BlobContainerClient client = blobServiceClient.GetBlobContainerClient("my-container");
BlobProperties properties = client.GetProperties()
long Length = properties.ContentLength;
At the initialization of the my seekable blob stream but the get properties is stuck and not returning back from the client
I tried this too
BlobContainerClient client = blobServiceClient.GetBlobContainerClient("my-container");
BlobProperties properties = client.GetPropertiesAsync().GetAwaiter().GetResult().Value;
long Length = properties.ContentLength;
The Nugets that I used there:
Azure.Storage.Blobs Version="12.10.0"
Microsoft.Azure.Management.Storage Version="23.0.0"
Thanks
I'm not sure what is the client in your client.GetProperties(). But you can get the length of the blob's content with the BlobProperties.ContentLength, as shown below example.
BlobServiceClient blobServiceClient = new BlobServiceClient("connectionString");
BlobContainerClient container = blobServiceClient.GetBlobContainerClient("containerName");
BlobClient blob = container.GetBlobClient("blobName");
var properties = blob.GetProperties();
Console.WriteLine(properties.Value.ContentLength);
Instead of printing the length as shown in the above example you can store it.

Get URI of uploaded blob?

Consider the following code:
// _blobContainerClient is an instance of BlobContainerClient
await _blobContainerClient.UploadBlobAsync(uniqueName, stream);
string uri = < how to get the URI? >
How do I get the URI of the uploaded blob?
I am using Azure.Storage.Blobs 12.8.0.
You just need to create a client and return the Uri this,
var blob = new BlobClient(connectionString, containerName, fileName);
await blob.UploadAsync(fileStream, o);
return ReturnUri(blob.Uri);
If you want to do more things with the blob object, I would recommend creating a new BlobClient. If you just need the URI this should work as well:
var blobUri = $"{_blobContainerClient.Uri.AbsoluteUri}/{uniqueName}";

Display files from Azure Blob Storage by Azure function

I'm trying to get files and display them in my browser from Azure Blob Storage via an Azure function. I could manage to download the files when I navigate to the url but I couldn't display them as a static file/image in my browser.
I just want to display it in browser rather than downloading.
I've tried some sdk command but it didn't work. Here's what I've tried:
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
ILogger log)
{
var cloudStorageAccount =
CloudStorageAccount.Parse(AzureStorageConnectionString);
var cloudBlobClient =
cloudStorageAccount.CreateCloudBlobClient();
var cloudBlobContainer =
cloudBlobClient.GetContainerReference(
AzureStorageFilePath);
await cloudBlobContainer.CreateIfNotExistsAsync();
var blobName =
req.Query["name"];
var cloudBlockBlob =
cloudBlobContainer.GetBlockBlobReference(blobName);
var ms = new MemoryStream();
await cloudBlockBlob.DownloadToStreamAsync(ms);
return new FileContentResult(ms.ToArray(), cloudBlockBlob.Properties.ContentType);
}
Any ideas would be appreciated. Thanks!
Kindly check the content type of the file(s) which you want to display ,if the content type is "application/octet-stream" it will cause the file to download.
By default if content-type is not supplied azure sdk sets it as "application/octet-stream" which causes the file to download,set the correct content-type for the file ex :- for image it should be "image/jpeg".
Hopefully this should fix the issue.

upload azure blob using UploadFromStreamAsync Method

Problem
I am trying to generate Pdf and create MemoryStream object and trying to upload that stream to azure Blob Storage. I am already tried the below code so far but the blob is not uploaded to azure and also what is the name of that blob which I upload using stream method of azure sdk
Code
var memoryStream = new MemoryStream(byteArray, 0, byteArray.Length);
var cred = new StorageCredentials("foo", "key");
var account = new CloudStorageAccount(cred, true);
var client = account.CreateCloudBlobClient();
var container = client.GetContainerReference("container");
CloudBlockBlob sourceBlob = container.GetBlockBlobReference("foo/bar");
var attachment = sourceBlob.UploadFromStreamAsync(memoryStream);
As #Kirk has said, use await sourceBlob.UploadFromStreamAsync(memoryStream); instead of var attachment = sourceBlob.UploadFromStreamAsync(memoryStream); Or your code will exit before upload is finished.
Note that your method should change to public async Task methodname(), you will see related tip shown by VS.
Some references for you
Async and Await
How and when to use async and-await
And see container.GetBlockBlobReference("blobname"); the string you use to get blob reference is the name of blob uploaded.

Uploading file to azure blob storage then sending http response with the files base64 string doesn't work

I am trying to achieve the following using azures blob storage.
Upload a file to azure blob storage.
Then send a http response containing a base64 string of the file.
The strange part is that I can get only one to work as it causes the other to stop working depending on the order of my code.
HttpPostedFile image = Request.Files["froalaImage"];
if (image != null)
{
string fileName = RandomString() + System.IO.Path.GetExtension(image.FileName);
string companyID = Request.Form["companyID"].ToLower();
// 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(companyID);
// Create the container if it doesn't already exist.
container.CreateIfNotExists();
// Retrieve reference to a blob named "filename".
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
// Create or overwrite the blob with contents from a local file.
using (image.InputStream)
{
blockBlob.UploadFromStream(image.InputStream);
byte[] fileData = null;
using (var binaryReader = new BinaryReader(image.InputStream))
{
fileData = binaryReader.ReadBytes(image.ContentLength);
}
string base64ImageRepresentation = Convert.ToBase64String(fileData);
// Clear and send the response back to the browser.
string json = "";
Hashtable resp = new Hashtable();
resp.Add("link", "data:image/" + System.IO.Path.GetExtension(image.FileName).Replace(#".", "") + ";base64," + base64ImageRepresentation);
resp.Add("imgID", "BLOB/" + fileName);
json = JsonConvert.SerializeObject(resp);
Response.Clear();
Response.ContentType = "application/json; charset=utf-8";
Response.Write(json);
Response.End();
}
}
The above code will upload the file to azure's blob storage however the base64 string will be empty.
But if I put the line blockBlob.UploadFromStream(image.InputStream); below the line string base64ImageRepresentation = Convert.ToBase64String(fileData);
I will get the base64 string no problem however the file is not uploaded correctly to azure's blob storage.
Maybe you need to reset your stream position after the first usage?
image.InputStream.Seek(0, SeekOrigin.Begin);

Categories

Resources