Nathan Foss
Nathan Foss

Reputation: 680

Azure Blob Storage Pass Metadata from Upload to Blob Trigger

I am developing a set of Azure Functions to do this high-level process

Everything works except for the last part.

When the PDF is uploaded to blob storage, we have access to the request metadata but the blob trigger only has access to the PDF Stream that was uploaded.

I've tried the following:

Document Upload

 var context = new OperationContext();
 context.UserHeaders = new Dictionary<string, string>();
 context.UserHeaders.Add("RowKey", entity.RowKey);
 context.UserHeaders.Add("PartitionKey", entity.PartitionKey);
 cloudBlockBlob.UploadFromStream(downloadedStream, operationContext: context);

Blob Trigger Private Method

public static void Run(
        [BlobTrigger(FunctionConstants.PrintSetToBlobName, Connection = ConnectionStringName)]Stream myBlob, 
        string name, 
        TraceWriter log)
{
     // code truncated for clarity
     string documentUrl = GetDocumentUrl();
     UpdateEntity(documentUrl);
}

private static void UpdateEntity(string documentUrl)
{
        // This doesn't seem like it will work
        OperationContext context = new OperationContext();
        EntityService entityService = new EntityService();

        context.UserHeaders.TryGetValue("RowKey", out string rowKey);
        context.UserHeaders.TryGetValue("PartitionKey", out string partitionKey);

        var entity = entityService.Get(rowKey, partitionKey);

        entity.DocumentUrl = documentUrl;
        entityService.Update(entity);
}

I've tried passing OperationContext directly as a parameter in the BlobTrigger.Run function but get runtime errors because it's not a valid input.

Ultimately, my question is how can I pass metadata from the CloudBlockBlob.UploadFromStream method and read it in the Blob Trigger?

Upvotes: 0

Views: 1327

Answers (1)

Lukas Kabrt
Lukas Kabrt

Reputation: 5489

UserHeaders sets HTTP headers for request that uploads the blob to Azure storage. These headers can't be available in the BlobTrigger, so you can't use them to pass additional parameters.

You can save PartitionKey and RowKey to the blob metadata:

cloudBlockBlob.Metadata["PartitionKey"] = entity.PartitionKey;
cloudBlockBlob.Metadata["RowKey"] = entity.RowKey;
cloudBlockBlob.SetMetadata();

And in your other function bind BlobTrigger to CloudBlockBlob

public static void Run(
    [BlobTrigger(FunctionConstants.PrintSetToBlobName, Connection = ConnectionStringName)]CloudBlockBlob cloudBlockBlob, 
    string name, 
    TraceWriter log)
{
    ...
} 

and read the metadata

cloudBlockBlob.FetchAttributes();
var partitionKey = cloudBlockBlob.Metadata["PartitionKey"];
var rowKey = cloudBlockBlob.Metadata["RowKey"];

Upvotes: 2

Related Questions