Display files from Azure Blob Storage by Azure function - c#

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.

Related

Sending list of images to azure function to upload image to blob in .Net

I am trying to upload images to blob from my android app. My current approach is uploading images using azureblobsdk which allows me to upload images directly to the blob but now what I am trying is creating an azure function that would accept data in stream or byte array and will store it to my blob.
while uploading the image from my app I used to send some metadata in the string to my app.
var blobClient = containerClient.GetBlobClient(fileName);
Dictionary<string, string> metadataProperties = new Dictionary<string, string>();
metadataProperties.Add(key, value);
await blobClient.SetMetadataAsync(metadataProperties);
here is what I am doing right now from the app
now I am trying this same thing to do from azure by sending those parameters to the azure function but the problem is I am unable to understand how would I send those streams and metadata to the azure function so that I can process them in my azure function
here is till now what I have done since I am new to azure function so need help to move forward with some approach
[FunctionName("UploadProductImages")]
public async Task<HttpResponseMessage> UploadProductImages([HttpTrigger(AuthorizationLevel.Function, "post", Route = "product/uploadimages")] HttpRequestMessage req, Microsoft.Extensions.Logging.ILogger log)
{
}
now with this function in place how do I access the data sent from my app which would be a list of images with metadata I am even confused about what should I send a stream or byte array
my final target is to get the list of images with some metadata of those images and upload to blob azure blob storage
If I understand the problem correctly, you can do something like this
Create a Model for you data and send it like this
HttpClient apiClient = new HttpClient();
using (var message = new HttpRequestMessage(HttpMethod.Post, functionAppLink))
{
message.Content = new StringContent(JsonConvert.SerializeObject(model),Encoding.UTF8, "application/json");
var response = await apiClient.SendAsync(message);
}
On Function app side just retrieve and deserialize
[FunctionName("UploadProductImages")]
public async Task<HttpResponseMessage> UploadProductImages([HttpTrigger(AuthorizationLevel.Function, "post", Route = "product/uploadimages")] HttpRequestMessage req, Microsoft.Extensions.Logging.ILogger log)
{
using var sr = new StreamReader(req.Body);
var input = await sr.ReadToEndAsync();
var model = JsonConvert.Deserialize<Model>(input);
// Do your thing
}

Error: Cannot convert from Microsoft.AspNetCore.Http.IFormFile to System.IO.Stream

I'm trying to create Azure function which takes image file from html form POST request and saves it to Blob Storage for further usage with another function. Here is my code:
public static class Function2
{
[FunctionName("Function2")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
foreach (var file in req.Form.Files)
{
using (var ms = new MemoryStream())
{
var file2 = req.Form.Files[0];
await file2.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);
var connectionString = "DefaultEndpointsProtocol=https;" +
"AccountName=mystorageaccount;" +
"AccountKey=8Hk5k6j65j5j665j67k==;" +
"EndpointSuffix=core.windows.net";
// intialize BobClient
Azure.Storage.Blobs.BlobClient blobClient = new Azure.Storage.Blobs.BlobClient(
connectionString: connectionString,
blobContainerName: "image-storage",
blobName: "images");
// upload the file
blobClient.Upload(file2);
}
}
return new OkResult("Image uploaded successfully");
}
}
However this raises exception:
Error CS1503 Argument 1: cannot convert from
'Microsoft.AspNetCore.Http.IFormFile' to 'System.IO.Stream'
Any advise would be very highly appreciated.
Edit: I have previously created Blob Container "image-storage" to my storage account using Azure Portal.
BlobCients Upload method expects a Stream instead of an IFormFile.
Passing the MemoryStream you have in the ms variable will resolve the issue.
blobClient.Upload(ms);

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.

Azure Function Access CloudBlobContainer from HttpTriggerFunction

Very, very new to Azure Functions and getting very frustrated.
All I want to do is execute on a 'get' request from a HttpTriggerFunction and return stream content from the CloudBlobContainer.
I really don't see why this is so hard. Just trying to host a SPA using Azure Functions.
Something like this
public static class UIHandler
{
[FunctionName("UIHandler")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]HttpRequest req,
TraceWriter log,
CloudBlobContainer container)
{
log.Info("C# HTTP trigger function processed a request.");
var stream = await container.GetBlockBlobReference({Infer file name from request here}).OpenReadAsync();
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(stream)
};
}
}
When I try to run this I get the following error.
Run: Microsoft.Azure.WebJobs.Host: Error indexing method
'UIHandler.Run'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter
'container' to type CloudBlobContainer. Make sure the parameter Type
is supported by the binding. If you're using binding extensions (e.g.
ServiceBus, Timers, etc.) make sure you've called the registration
method for the extension(s) in your startup code (e.g.
config.UseServiceBus(), config.UseTimers(), etc.).
I'm using Azure Functions 2. I can't see from the web how to setup the browsing extensions for this. Iv'e also looked into Input and Output bindings. I don't understand what makes a parameter input or output bound when your using C# that only seems to exist in the JSON.
Do I need to corresponding JSON file ? If so what is it called where does it go.
Thanks in Advance
Have a look at Blob Storage Input Binding. The very first sample there shows how to read blob stream, just replace Queue Trigger with HTTP trigger, e.g.
[FunctionName("UIHandler")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "{name}")] HttpRequest req,
string name,
TraceWriter log,
[Blob("samples-workitems/{name}", FileAccess.Read)] Stream stream)
{
log.Info($"C# HTTP trigger function processed a request for {name}.");
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(stream)
};
}

Download a file from Azure blob storage

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;
}

Categories

Resources