MD5 value of upload file - azure

I'm trying to extract MD5 and length (size) of the upload blob using Azure function using Http Trigger, Below the code im experimenting, but I always get null and -1. Please someone confirm the code is correct or any other option is available
public static async Task<IActionResult> Run(HttpRequest req,string inputBlob, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
log.LogInformation($"name,{inputBlob}");
log.LogInformation("Blob content: " + inputBlob.Properties.Length); //This is printing content of blob
CloudBlockBlob blob;
var credentials = new StorageCredentials("xxx", "xxxx");
var client = new CloudBlobClient(new Uri("https://xxx.blob.core.windows.net"), credentials);
var container = client.GetContainerReference("parent");
blob = container.GetBlockBlobReference("file.csv");
log.LogInformation("Blob details: " + blob.Properties.Length); //This is printing -1, if i provide ContentMD5 its showing null. Bascially its not able to read the blob
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}

You are missing FetchAttributesAsync() (or FetchAttributes()) method before you try to retrieve any properties of the blob.
//your other code
blob = container.GetBlockBlobReference("file.csv");
blob.FetchAttributesAsync()(); //or FetchAttributes()
//then you can try to get any property here.

Related

how to use basic authentication on azure functions ISOLATED?

how do i get the user and password informed in basic authentication in azure functions ISOLATED?
exemple, using the app SOAPUI to make a call to the function:
[https://i.imgur.com/3u7eymT.png]
how do i get in the function this USER and his password ?
[Function("Function1")]
public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
response.WriteString("Welcome to Azure Functions!");
return response;
}
i also have a middleware how i get this info in him too?
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
i tried to search in the header, or the identities but i can't find this info/login and password
For Basic Authentication we need to change the open API security property values as below
[OpenApiSecurity("basic_auth", SecuritySchemeType.Http, Scheme = OpenApiSecuritySchemeType.Basic)]
Below is the screenshot of SoapUI
Authorization header need to be added in SoapUI as shown below
Code In Function
var headers = req.Headers["Authorization"];
if (ValidateToken(headers))
{
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
string responseMessage = string.IsNullOrEmpty(name) ? "Pass a name in the query string" : $"{name}";
return new OkObjectResult(responseMessage);
}
Validation Code part
string encode_Credentials = header.Substring("Basic ".Length).Trim();
Encoding encode = Encoding.GetEncoding("iso-8859-1");
string credentials = encode.GetString(Convert.FromBase64String(encode_Credentials));
int seperatorIndex = credentials.IndexOf(':');
var username = credentials.Substring(0, seperatorIndex);
var password = credentials.Substring(seperatorIndex + 1);
if (username is "Rajesh" && password is "1142") return true;
else return false;

BlockBlobClient.UploadAsync fails when trying to modify the incoming WatchableReadStream object

I hope you're having some advice because I'm pretty much out of options. What I'm trying to do:
upload an image to a blobcontainer via the azure portal
when doing that, the blobtrigger below fires.
I want to resize the incoming image which is a Microsoft.Azure.WebJobs.Host.Blobs.WatchableReadStream object.
I want to upload the result to a new blob container.
The issue is, when I am passing any other Stream, e.g. a MemoryStream than the unmodified myBlob object the UploadAsync method seems to silently fail and the BlobTrigger fires again, starting an endless loop. Writing to the current myBlob object also silently fails. Only thing which works is passing the myBlob object in BlockBlobClient.UploadAsync without ANY modification whatsoever, which is useless. I am doing a remote debugging session in Azure.
Also, when I try to feed a MemoryStream object to the UploadAsync method the same problem occurs. The method below is the blob trigger:
public async Task UploadImage([BlobTrigger("mediafullsizecontainer/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, ILogger log)
{
BlockBlobClient fullsizeBlobClient = _mediaFullsizeContainerClient.GetBlockBlobClient(name);
Response<BlobProperties> blobPropertiesResponse = await fullsizeBlobClient.GetPropertiesAsync(null, default);
BlobProperties blobProperties = blobPropertiesResponse.Value;
//Only process blobs when the correct metadata properties are set
if (blobProperties.Metadata.Any(property => property.Key == "category" & property.Value != String.Empty))
{
string category = blobProperties.Metadata["category"];
Stream s = await ResizeImage(myBlob);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(s, new BlobUploadOptions(), default);
BlobContentInfo blobContentInfo = uploadResponse.Value;
}
}
The ResizeImage method uses the SixLabors.ImageSharp image processing library.
public async Task<Stream> ResizeImage(Stream inputStream)
{
(Image image, IImageFormat imageFormat) imageWithFormat = await Image.LoadWithFormatAsync(inputStream);
int height = imageWithFormat.image.Height;
int width = imageWithFormat.image.Width;
imageWithFormat.image.Mutate(operation => {
operation.Resize(width / 4, height / 4);
});
MemoryStream outputStream = new MemoryStream();
imageWithFormat.image.Save(outputStream, imageWithFormat.imageFormat);
return outputStream;
}
So when I do a mock change on the myBlob object like this, myBlob.Write(buffer) fails:
byte[] buffer = new byte[myBlob.Length];
myBlob.Read(buffer, 0, (int)myBlob.Length);
myBlob.Position = 0;
myBlob.Write(buffer);
When I copy the myBlob contents to a MemoryStream and pass the memoryStream to UploadAsync, UploadAsync fails:
MemoryStream ms = new MemoryStream();
myBlob.CopyTo(ms);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(ms, new BlobUploadOptions(), default);
Only thing which works is passing the myBlob object without any modification to UploadAsync which is useless since I need to modify the incoming stream:
public async Task UploadImage([BlobTrigger("mediafullsizecontainer/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, ILogger log)
{
BlockBlobClient fullsizeBlobClient = _mediaFullsizeContainerClient.GetBlockBlobClient(name);
Response<BlobProperties> blobPropertiesResponse = await fullsizeBlobClient.GetPropertiesAsync(null, default);
BlobProperties blobProperties = blobPropertiesResponse.Value;
//Only process blobs when the correct metadata properties are set
if (blobProperties.Metadata.Any(property => property.Key == "category" & property.Value != String.Empty))
{
string category = blobProperties.Metadata["category"];
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Response<BlobContentInfo> uploadResponse = await thumbnailBlobclient.UploadAsync(myBlob, new BlobUploadOptions(), default);
BlobContentInfo blobContentInfo = uploadResponse.Value;
}
}
How can I pass a custom stream to the UploadAsync method? The documentation on https://learn.microsoft.com/en-us/dotnet/api/azure.storage.blobs.specialized.blockblobclient.uploadasync?view=azure-dotnet says you just need a stream object - but this does not work. Thanks in advance.
Ok looks like I found the answer myself, I got rid of the dreaded UploadAsync method and did it like this by reading the outputStream of the resized image into a buffer then opening a Stream for writing to the thumbnailBlobclient object and passing the buffer to the stream object. It makes sense that trying to modify the incoming myBlob object which came with the trigger, fires the trigger again and creating a loop.
Stream outputStream = await ResizeAndCropImage(myBlob);
byte[] buffer = new byte[outputStream.Length];
outputStream.Read(buffer);
BlockBlobClient thumbnailBlobclient = _mediaThumbnailContainerClient.GetBlockBlobClient(name);
Stream s = thumbnailBlobclient.OpenWrite(true, new BlockBlobOpenWriteOptions { HttpHeaders = new BlobHttpHeaders { ContentType = "image/jpg" } }, default); //set http headers here as well?
await s.WriteAsync(buffer);
s.Close();
I will set the content type in a more generic way but this concept is working.

azure blob client returns file not fully

i'm trying to download file from azure blob storage, but it returns only part of file. What i'm doing wrong ? File in storage is not corrupted
public async Task<byte[]> GetFile(string fileName)
{
var blobClient = BlobContainerClient.GetBlobClient(fileName);
var downloadInfo = await blobClient.DownloadAsync();
byte[] b = new byte[downloadInfo.Value.ContentLength];
await downloadInfo.Value.Content.ReadAsync(b, 0, (int)downloadInfo.Value.ContentLength);
return b;
}
I'm using Azure.Storage.Blobs 12.4.2 package. I tried this code and it works for me
public async Task<byte[]> GetFile(string fileName)
{
var blobClient = BlobContainerClient.GetBlobClient(fileName);
using (var memorystream = new MemoryStream())
{
await blobClient.DownloadToAsync(memorystream);
return memorystream.ToArray();
}
}
I am not able to full understand your code as the current BlobClient as of v11.1.1 does not expose any download methods. As #Guarav Mantri-AIS mentioned the readAsync can behave in that manner.
Consider an alternative using the DownloadToByteArrayAsync() which is part of the API. I have include the code required to connect but of course this is just for the purpose of demonstrating a full example.
Your method would be condensed as follows:
public async Task<byte[]> GetFile(string containerName, string fileName)
{
//i am getting the container here, not sure where or how you are doing this
var container = GetContainer("//your connection string", containerName);
//Get the blob first
ICloudBlob blob = container.GetBlockBlobReference(fileName);
//and now download it straight to a byte array
return await blobClient.DownloadAsync();
}
public CloudBlobContainer GetContainer(string connectionString, string containerName)
{
//1. connect to the account
var account = CloudStorageAccount.Parse(connectionString);
//2. create a client
var blobClient = _account.CreateCloudBlobClient();
//3. i am getting the container here, not sure where or how you are doing this
return = _blobClient.GetContainerReference(containerName);
}

Azure Function Status Code 500 internal server error

I have a logic app that uses azure function as a http trigger and gets a return string.
When the azure function is to receive a Base64 string, create a file with the information and uploads to the assigned storage account, I keep getting status code 500 internal server error from the Azure function every time I run it. After many trial and error I deduced the problem occurs from when the file is to be created from the Base64 string and when the blob container client is created.
So Help me Please.
UPDATE: As per some of your suggestions, I implemented application insights ran it a few times and got this error occuring twice:
Azure.RequestFailedException
Message: Exception while executing function: BlobAdd The specifed resource name contains invalid characters
Status: 400 (The specifed resource name contains invalid characters.)
ErrorCode: InvalidResourceName
FailedMethod: Azure.Storage.Blobs.BlobRestClient+Container.CreateAsync_CreateResponse.
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.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
return await Base64(requestBody);
}
public static async Task<IActionResult> Base64(string Base64Body)
{
string HoldDBase = "";
string TestBlobData = "null";
if (Base64Body.Length > 10)
{
HoldDBase = Base64Body;
}
else
{
TestBlobData = "The Base64Body did not Pass";
return (ActionResult)new OkObjectResult
(
new
{
TestBlobData
}
);
}
//Connection string of the Storage Account Azure
string ConnectionString = "xxxxxxxxx";
// Create a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(ConnectionString);
//Create a unique name of the container
string ContainerName = "Base64_Blob" + Guid.NewGuid().ToString();
//create the container and return a container client Object
BlobContainerClient ContainerClient = await blobServiceClient.CreateBlobContainerAsync(ContainerName); //Problem Here
//create a local file in the Storage
string localPath = "D:/Reliance/OlaForm/uploadsO";
string fileName = "quickstart" + Guid.NewGuid().ToString() + ".txt";
string localFilePath = Path.Combine(localPath, fileName);
//convert string to bytes
byte[] BaseBytes = Convert.FromBase64String(HoldDBase);
//create file in local data
await File.WriteAllBytesAsync(localFilePath,BaseBytes); //Problem Here
//get reference to a blob
BlobClient blobclient = ContainerClient.GetBlobClient(fileName);
// Open the file and upload its data
FileStream uploadFileStream = File.OpenRead(localFilePath);
await blobclient.UploadAsync(uploadFileStream);
// blobclient.Upload(uploadFileStream);
uploadFileStream.Close();
//blob id from blobclient and return it
TestBlobData = blobclient.ToString();
TestBlobData = HoldDBase;
return (ActionResult)new OkObjectResult
(
new {
TestBlobData
}
);
}
You are trying to write to the "D" disk. Since the Azure function does not have direct access to disks, you get a 500 error when trying to write to a disk that does not exist.
To write to a file from an Azure function you can use the Azure Storage SDK.

Uploading ID to same Azure Blob Index that a file is being uploaded to using .Net SDK

I am uploading documents to my an Azure Blob Storage, which works perfect, but I want to be able to link and ID to this specifically uploaded document.
Below is my code for uploading the file:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
try
{
var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"), file.FileName);
string searchServiceName = ConfigurationManager.AppSettings["SearchServiceName"];
string blobStorageKey = ConfigurationManager.AppSettings["BlobStorageKey"];
string blobStorageName = ConfigurationManager.AppSettings["BlobStorageName"];
string blobStorageURL = ConfigurationManager.AppSettings["BlobStorageURL"];
file.SaveAs(path);
var credentials = new StorageCredentials(searchServiceName, blobStorageKey);
var client = new CloudBlobClient(new Uri(blobStorageURL), credentials);
// Retrieve a reference to a container. (You need to create one using the mangement portal, or call container.CreateIfNotExists())
var container = client.GetContainerReference(blobStorageName);
// Retrieve reference to a blob named "myfile.gif".
var blockBlob = container.GetBlockBlobReference(file.FileName);
// Create or overwrite the "myblob" blob with contents from a local file.
using (var fileStream = System.IO.File.OpenRead(path))
{
blockBlob.UploadFromStream(fileStream);
}
System.IO.File.Delete(path);
return new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = "Success"
};
}
catch (Exception ex)
{
throw;
}
}
I have added the ClientID field to the Index(It is at the bottom), but have no idea how I am able to add this to this index. This is still al nerw to me and just need a little guidance if someone can help :
Thanks in advance.

Resources