upload azure blob using UploadFromStreamAsync Method - c#

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.

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
}

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

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

AWS C# lambda File upload to S3

I have created a Serverless for AWS using visual studio empty template. I am trying to send a file to it which internally gets uploaded to S3 using C#. I am able to upload the file through a console application. I need help on:
a. how to send file to API through Insomnia or Postman -- able to do it now
b. How the receive the file so that when I upload it S3 I am able to download it directly the way I sent in the API.-- able to do it now
[EDIT]
c. When trying to save the file to bucket the file size is less than the uploaded and is corrupted.
Code Snippet:
public APIGatewayProxyResponse Get(APIGatewayProxyRequest request, ILambdaContext context)
{
context.Logger.LogLine(Encoding.ASCII.GetByteCount(request.Body).ToString());
MemoryStream ms = new MemoryStream();
TransferUtility utility = new TransferUtility(new AmazonS3Client("<AccessKey>", "<SecretKey>", Amazon.RegionEndpoint.USEast1));
var checker = new TransferUtilityUploadRequest()
{
InputStream = new MemoryStream(Encoding.ASCII.GetBytes(request.Body)),
BucketName = "<BucketName>",
Key = "<FileName>.pdf"
};
utility.Upload(checker);
var response = new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.OK,
Body = JsonConvert.SerializeObject(checker),
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" }, { "Access-Control-Allow-Origin", "*" } }
};
return response;
}
Note: The file could be docx or pdf. Also I have the code to upload file stream to S3 Just need info on receiving the file through APIGatewayProxyRequest type and converting to stream.
Thanks in advance.

Download Azure blob and set it as data url on an image tag

I'm trying to download a blob from private Azure Blob storage container and display it in an image tag.
On the question below you can see how I'm returning the blob from the Web API in Stream format.
Getting 403 error when trying to retrieve an Azure blob on Web API request
From the HTTP response, I am able to retrieve the content type of the blob by including it on the headers section of the request. To use it to generate the data URI to be used on the image tag. I understand I need to convert the Stream into a base64 string to be able to include it on the src attribute of an image tag. I'm currently struggling to convert the result from the HTTP request into a base64 string.
I have created this js fiddle which contains the data (image) received from the HTTP request along with my attempt to convert the data into a base64 string:
'http://jsfiddle.net/chesco9/6a7ohgho/'
EDIT
Thank you Tom for your help. I was able to implement your solution and it worked out. I had been stuck on this problem for a few days now.
public async Task<AzureBlobModel> DownloadBlob(Guid blobId)
{
try
{
//get picture record
Picture file = await _media.GetPictureAsync(blobId);
// get string format blob name
var blobName = file.PictureId.ToString() + file.Extension;
if (!String.IsNullOrEmpty(blobName))
{
var blob = _container.GetBlockBlobReference(blobName);
// Strip off any folder structure so the file name is just the file name
var lastPos = blob.Name.LastIndexOf('/');
var fileName = blob.Name.Substring(lastPos + 1, blob.Name.Length - lastPos - 1);
var fileLength = blob.Properties.Length;
var stream = await blob.OpenReadAsync();
MemoryStream ms = new MemoryStream();
stream.CopyTo(ms);
var result = new AzureBlobModel()
{
FileName = fileName,
FileSize = blob.Properties.Length,
Stream = stream,
ContentType = blob.Properties.ContentType,
StreamBase64 = Convert.ToBase64String(ms.ToArray())
};
return result;
}
}
catch(Exception ex)
{
await _log.CreateLogEntryAsync("exception thrown: " + ex.ToString());
}
await _log.CreateLogEntryAsync("returning null");
// Otherwise
return null;
}
I'm currently struggling to convert the result from the HTTP request into a base64 string.
Base on my understanding, now you can download the blob from the Azure storage.
According to your mentioned link, the WebApi return the AzureBlobModel.
We can convert the stream to base64 string easily with C# code backend.You can add following code in your code. If it is prossible, return this value in the AzureBlobModel.
MemoryStream ms = new MemoryStream();
stream.CopyTo(ms);
string strBase64 = Convert.ToBase64String(ms.ToArray());

Categories

Resources