c# - 模式匹配 blob 名称到具有输入绑定(bind)的函数变量

标签 c# azure-functions azure-blob-storage

根据Azure Blob storage bindings for Azure Functions documentation ,在配置 blob 触发器时,您可以利用 blob 名称上的模式匹配将部分路径映射到函数中的变量,例如。

[FunctionName("BlobTriggered")]        
public static void BlobTriggered(
    [BlobTrigger("myContainer/{name}.{extension}")] Stream myBlob,
    string name,
    string extension,
    TraceWriter log)
{
    // Given the blob path "myContainer/myBlob.png":
    // name == "myBlob"
    // extension == "png"
}

我已经对此进行了测试,它非常适合我的用例,但是由于 BlobTrigger 触发的延迟很大(通常超过 5 分钟),它不是一个可行的选择。因此,我希望按照 Azure Functions scale and hosting documentation 的建议将其设为事件网格触发器。 :

When you're using a blob trigger on a Consumption plan, there can be up to a 10-minute delay in processing new blobs. This delay occurs when a function app has gone idle. After the function app is running, blobs are processed immediately. To avoid this cold-start delay, use an App Service plan with Always On enabled, or use the Event Grid trigger.

有什么方法可以从输入绑定(bind)而不是触发器获得相同的模式匹配行为?

在我的具体情况下,我已经为 blob 创 build 置了一个 EventGrid 订阅,它运行一个协调器函数调用一个事件函数来读取和解析 blob:

[FunctionName("NewBlobCreated")]
public static async Task NewBlobCreated(
    [EventGridTrigger]EventGridEvent eventGridEvent,
    [OrchestrationClient]DurableOrchestrationClient starter,
    ILogger log)
{
    // Start our orchestrator function to read the file
    string instanceId = await starter.StartNewAsync(
        "OrchestrateBlobReader",
        eventGridEvent);
}

// Orchestrator function
[FunctionName("OrchestrateBlobReader")]
public static async Task OrchestrateBlobReader(
    [OrchestrationTrigger] DurableOrchestrationContext context,
    ILogger log)
{
    var eventGridEvent = context.GetInput<EventGridEvent>();
    var parsedBlob = await context.CallActivityAsync<string>("ReadBlob", eventGridEvent.Data);        
    ...
}

[FunctionName("ReadBlob")]
public static async Task<string> ReadBlob(
    [ActivityTrigger] JObject eventData,
    [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
    ILogger log)
{
    using (var blobStream = await blob.OpenReadAsync())
    {
        // Blob is able to be read from blobStream here
        ...
    }
}

理想情况下,我希望我的 ReadBlob 函数的行为类似于上面第一个示例中的 BlobTriggered 函数,以执行以下操作:

[FunctionName("ReadBlob")]
public static async Task<string> ReadBlob(
    [ActivityTrigger] JObject eventData,
    [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
    string extension,
    ILogger log)
{
    if (extension.Equals("txt", StringComparison.OrdinalIgnoreCase))
    { ... }
    else if (extension.Equals("png", StringComparison.OrdinalIgnoreCase)
    { ... }
    else
    { ... }
}

问题是我看不到任何方法可以将 extension 参数绑定(bind)到 Blob 输入绑定(bind),就像我为 BlobTrigger 所做的那样> - 特别是路径被绑定(bind)到 EventGridEvent 提供的 url 以 eventData JObject 的形式。

在这种情况下是否可以实现相同的模式匹配功能?还是我必须自己解析路径字符串以提取相关信息?

最佳答案

在查看了 blob 触发器绑定(bind)的源代码之后 - 我的“快速而肮脏”的解决方案是利用底层 BindingTemplateSource class触发器用于将路径和模式映射到字典。

更新后的ReadBlob函数如下:

// So we can access the BindingTemplateSource class
using Microsoft.Azure.WebJobs.Host.Bindings.Path;

[FunctionName("ReadBlob")]
public static async Task<string> ReadBlob(
    [ActivityTrigger] JObject eventData,
    [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
    ILogger log)
{
    // Define the pattern to match
    var blobPattern = "myContainer/{name}.{extension}";
    // Create a BindingTemplateSource from the pattern string
    var patternTemplate = BindingTemplateSource.FromString(blobPattern);
    // Use this BindingTemplateSource to create the binding data
    // This returns a IReadOnlyDictionary<string, object> with the parameters mapped
    var parameters = patternTemplate.CreateBindingData($"{blob.Container.Name}/{blob.Name}");
    // Assuming blob path was "myContainer/myBlob.png":
    // Parameters are objects so we need to ToString() them
    var name = parameters["name"].ToString(); // name == "myBlob"
    var extension = parameters["extension"].ToString(); // extension == "png"

    if (extension.Equals("txt", StringComparison.OrdinalIgnoreCase))
    { ... }
    else if (extension.Equals("png", StringComparison.OrdinalIgnoreCase))
    { 
        // This executes now!
    }
    else
    { ... }
}

此功能可能会被包装在 custom binding 中其中参数被映射到函数的输出绑定(bind),就像 BlobTrigger 为最优雅的解决方案所做的那样,但是像这样将它侵入函数可以实现我短期内需要的东西

关于c# - 模式匹配 blob 名称到具有输入绑定(bind)的函数变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52771563/

相关文章:

c# - MYSQL Connector.net 连接长时间后丢失

c# - 数据库中不同列的数据计数

azure - 从 Javascript 文件调用 Azure 函数

具有特定权限集的 Blob 存储的 Azure 角色

c# - 如何获取长字符串并将其滚动到 15 个字符的文本控件/标签中?

c# - 将数组对转换为数组对(如果可能,使用 LINQ)

azure - 如何使用 FileUpload 在 Azure Blob 中上传文件大小大于 1 GB 的 asp.net 文件

c# - 有没有办法从 azure blob 的容器文件夹中获取所有子文件夹名称?

现有 Azure 应用服务上的 Azure Function

c# - 使用托管身份在另一个函数应用程序中调用 http 触发的函数应用程序