Azure Functions 的 Azure Blob 存储绑定

本文介绍如何在 Azure Functions 中使用 Azure Blob 存储绑定。 Azure Functions 支持 Blob 的触发器、输入和输出绑定。 本文各部分分别介绍每种绑定:

此参考信息面向 Azure Functions 开发人员。 Azure Functions 的新手请从以下资源入手:

包 - Functions 1.x

Microsoft.Azure.WebJobs NuGet 包 2.x 版中提供了 Blob 存储绑定。 azure-webjobs-sdk GitHub 存储库中提供了此包的源代码。

Functions 2.x 中的绑定扩展

对于 Azure Functions 2.x 版中的本地开发,该包自动注册为绑定扩展

Functions 1.x 中的 Azure 存储 SDK 版本

在 Functions 1.x 中,存储触发器和绑定使用 7.2.1 版的 Azure 存储 SDK(WindowsAzure.Storage NuGet 包)。 如果引用另一版本的存储 SDK,而且在函数签名中绑定到某个存储 SDK 类型,则 Functions 运行时可能会报告它不能绑定到该类型。 此解决方案是为了确保项目引用 WindowsAzure.Storage 7.2.1

包 - Functions 2.x

Microsoft.Azure.WebJobs.Extensions.Storage NuGet 包 3.x 版中提供了 Blob 存储绑定。 azure-webjobs-sdk GitHub 存储库中提供了此包的源代码。

下表说明了如何在每个开发环境中添加对此绑定的支持。

开发环境 添加支持
Functions 2.x
本地开发 - C# 类库 安装包
本地开发 - C# 脚本、JavaScript、F#、Java 和 Python 注册扩展
门户开发 添加输出绑定时安装

若要了解如何更新门户中的现有绑定扩展而不必重新发布函数应用项目,请参阅更新扩展

触发器

检测到新的或更新的 Blob 时,Blob 存储触发器会启动某个函数。 Blob 内容会作为输入提供给函数。

触发器 - 示例

参阅语言特定的示例:

触发器 - C# 示例

以下示例演示在 samples-workitems 容器中添加或更新 blob 时写入日志的 C# 函数

[FunctionName("BlobTriggerCSharp")]        
public static void Run([BlobTrigger("samples-workitems/{name}")] Stream myBlob, string name, ILogger log)
{
    log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
}

blob 触发器路径 samples-workitems/{name} 中的字符串 {name} 会创建一个绑定表达式,可以在函数代码中使用它来访问触发 blob 的文件名。 有关详细信息,请参阅本文下文中的 Blob 名称模式

有关 BlobTrigger 特性的详细信息,请参阅触发器 - 特性

触发器 - C# 脚本示例

以下示例显示了 function.json 文件中的一个 Blob 触发器绑定以及使用该绑定的 Python 代码。 在 samples-workitems 容器中添加或更新 Blob 时,该函数会写入一条日志。

下面是 function.json 文件中的绑定数据:

{
    "disabled": false,
    "bindings": [
        {
            "name": "myBlob",
            "type": "blobTrigger",
            "direction": "in",
            "path": "samples-workitems/{name}",
            "connection":"MyStorageAccountAppSetting"
        }
    ]
}

blob 触发器路径 samples-workitems/{name} 中的字符串 {name} 会创建一个绑定表达式,可以在函数代码中使用它来访问触发 blob 的文件名。 有关详细信息,请参阅本文下文中的 Blob 名称模式

有关 function.json 文件属性的详细信息,请参阅解释了这些属性的配置部分。

下面是绑定到 Stream 的 C# 脚本代码:

public static void Run(Stream myBlob, string name, ILogger log)
{
   log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
}

下面是绑定到 CloudBlockBlob 的 C# 脚本代码:

#r "Microsoft.WindowsAzure.Storage"

using Microsoft.WindowsAzure.Storage.Blob;

public static void Run(CloudBlockBlob myBlob, string name, ILogger log)
{
    log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name}\nURI:{myBlob.StorageUri}");
}

触发器 - JavaScript 示例

以下示例显示了 function.json 文件中的一个 Blob 触发器绑定以及使用该绑定的 JavaScript 代码。 在 samples-workitems 容器中添加或更新 Blob 时,该函数会写入日志。

function.json 文件如下所示:

{
    "disabled": false,
    "bindings": [
        {
            "name": "myBlob",
            "type": "blobTrigger",
            "direction": "in",
            "path": "samples-workitems/{name}",
            "connection":"MyStorageAccountAppSetting"
        }
    ]
}

blob 触发器路径 samples-workitems/{name} 中的字符串 {name} 会创建一个绑定表达式,可以在函数代码中使用它来访问触发 blob 的文件名。 有关详细信息,请参阅本文下文中的 Blob 名称模式

有关 function.json 文件属性的详细信息,请参阅解释了这些属性的配置部分。

JavaScript 代码如下所示:

module.exports = function(context) {
    context.log('Node.js Blob trigger function processed', context.bindings.myBlob);
    context.done();
};

触发器 - Python 示例

以下示例显示了 function.json 文件中的一个 Blob 触发器绑定以及使用该绑定的 Python 代码。 在 samples-workitems 容器中添加或更新 Blob 时,该函数会写入一条日志。

function.json 文件如下所示:

{
    "scriptFile": "__init__.py",
    "disabled": false,
    "bindings": [
        {
            "name": "myblob",
            "type": "blobTrigger",
            "direction": "in",
            "path": "samples-workitems/{name}",
            "connection":"MyStorageAccountAppSetting"
        }
    ]
}

blob 触发器路径 samples-workitems/{name} 中的字符串 {name} 会创建一个绑定表达式,可以在函数代码中使用它来访问触发 blob 的文件名。 有关详细信息,请参阅本文下文中的 Blob 名称模式

有关 function.json 文件属性的详细信息,请参阅解释了这些属性的配置部分。

下面是 Python 代码:

import logging
import azure.functions as func

def main(myblob: func.InputStream):
    logging.info('Python Blob trigger function processed %s', myblob.name)

触发器 - Java 示例

以下示例显示了 function.json 文件中的一个 Blob 触发器绑定以及使用该绑定的 Java 代码。 在 myblob 容器中添加或更新 Blob 时,该函数会写入日志。

function.json 文件如下所示:

{
    "disabled": false,
    "bindings": [
        {
            "name": "file",
            "type": "blobTrigger",
            "direction": "in",
            "path": "myblob/{name}",
            "connection":"MyStorageAccountAppSetting"
        }
    ]
}

下面是 Java 代码:

@FunctionName("blobprocessor")
public void run(
  @BlobTrigger(name = "file",
               dataType = "binary",
               path = "myblob/{name}",
               connection = "MyStorageAccountAppSetting") byte[] content,
  @BindingName("name") String filename,
  final ExecutionContext context
) {
  context.getLogger().info("Name: " + filename + " Size: " + content.length + " bytes");
}

触发器 - 特性

对于 C# 类库,请使用以下属性来配置 blob 触发器:

  • BlobTriggerAttribute

    该特性的构造函数采用一个表示要监视的容器的路径字符串,并选择性地采用某种 Blob 名称模式。 下面是一个示例:

    [FunctionName("ResizeImage")]
    public static void Run(
        [BlobTrigger("sample-images/{name}")] Stream image,
        [Blob("sample-images-md/{name}", FileAccess.Write)] Stream imageSmall)
    {
        ....
    }
    

    可以设置 Connection 属性来指定要使用的存储帐户,如以下示例中所示:

    [FunctionName("ResizeImage")]
    public static void Run(
       [BlobTrigger("sample-images/{name}", Connection = "StorageConnectionAppSetting")] Stream image,
       [Blob("sample-images-md/{name}", FileAccess.Write)] Stream imageSmall)
    {
       ....
    }
    

    有关完整示例,请参阅触发器 - C# 示例

  • StorageAccountAttribute

    提供另一种方式来指定要使用的存储帐户。 构造函数采用包含存储连接字符串的应用设置的名称。 可以在参数、方法或类级别应用该特性。 以下示例演示类级别和方法级别:

    [StorageAccount("ClassLevelStorageAppSetting")]
    public static class AzureFunctions
    {
        [FunctionName("BlobTrigger")]
        [StorageAccount("FunctionLevelStorageAppSetting")]
        public static void Run( //...
    {
        ....
    }
    

要使用的存储帐户按以下顺序确定:

  • BlobTrigger 特性的 Connection 属性。
  • 作为 BlobTrigger 特性应用到同一参数的 StorageAccount 特性。
  • 应用到函数的 StorageAccount 特性。
  • 应用到类的 StorageAccount 特性。
  • 函数应用的默认存储帐户(“AzureWebJobsStorage”应用设置)。

触发器 - 配置

下表解释了在 function.json 文件和 BlobTrigger 特性中设置的绑定配置属性。

function.json 属性 Attribute 属性 说明
类型 不适用 必须设置为 blobTrigger。 在 Azure 门户中创建触发器时,会自动设置此属性。
direction 不适用 必须设置为 in。 在 Azure 门户中创建触发器时,会自动设置此属性。 用法部分中已阐述异常。
name 不适用 表示函数代码中的 Blob 的变量的名称。
路径 BlobPath 要监视的容器。 可以是某种 Blob 名称模式
连接 Connection 包含要用于此绑定的存储连接字符串的应用设置的名称。 如果应用设置名称以“AzureWebJobs”开始,则只能在此处指定该名称的余下部分。 例如,如果将 connection 设置为“MyStorage”,函数运行时将会查找名为“AzureWebJobsMyStorage”的应用设置。 如果将 connection 留空,函数运行时将使用名为 AzureWebJobsStorage 的应用设置中的默认存储连接字符串。

连接字符串必须属于某个常规用途存储帐户,而不能属于Blob 存储帐户

在本地进行开发时,应用设置将取 local.settings.json 文件的值。

触发器 - 用法

在 C# 和 C# 脚本中,可以为触发 blob 使用以下参数类型:

  • Stream
  • TextReader
  • string
  • Byte[]
  • 可序列化为 JSON 的 POCO
  • ICloudBlob1
  • CloudBlockBlob1
  • CloudPageBlob1
  • CloudAppendBlob1

1 function.json 中需有 "inout" 绑定 direction 或 C# 类库中需有 FileAccess.ReadWrite

如果在尝试绑定到某个存储 SDK 类型时出现错误消息,请确保引用正确的存储 SDK 版本

由于整个 Blob 内容都会加载到内存中,因此,只有当 Blob 较小时才建议绑定到 stringByte[] 或 POCO。 平时,最好使用 StreamCloudBlockBlob 类型。 有关详细信息,请参阅本文后面的并发和内存使用情况

在 JavaScript 中,可以使用 context.bindings.<name from function.json> 访问输入 Blob 数据。

触发器 - Blob 名称模式

可以在 function.jsonpath 属性中或者在 BlobTrigger 特性构造函数中指定 Blob 名称模式。 名称模式可以是筛选器或绑定表达式。 以下部分提供了有关示例。

获取文件名和扩展名

以下示例演示如何分别绑定到 Blob 文件名和扩展名:

"path": "input/{blobname}.{blobextension}",

如果 Blob 名为 original-Blob1.txt,则函数代码中 blobnameblobextension 变量的值为 original-Blob1txt

按 Blob 名称筛选

以下示例仅根据 input 容器中以字符串“original-”开头的 Blob 触发:

"path": "input/original-{name}",

如果 Blob 名称为 original-Blob1.txt,则函数代码中 name 变量的值为 Blob1

按文件类型筛选

以下示例仅根据 .png 文件触发:

"path": "samples/{name}.png",

按文件名中的大括号筛选

若要查找文件名中的大括号,请使用两个大括号将大括号转义。 以下示例筛选名称中包含大括号的 Blob:

"path": "images/{{20140101}}-{name}",

如果 Blob 名为 {20140101}-soundfile.mp3,则函数代码中的 name 变量值为 soundfile.mp3

触发器 - 元数据

Blob 触发器提供了几个元数据属性。 这些属性可在其他绑定中用作绑定表达式的一部分,或者用作代码中的参数。 这些值的语义与 CloudBlob 类型相同。

属性 类型 说明
BlobTrigger string 触发 Blob 的路径。
Uri System.Uri 主位置的 blob 的 URI。
Properties BlobProperties Blob 的系统属性。
Metadata IDictionary<string,string> Blob 的用户定义元数据。

例如,以下 C# 脚本和 JavaScript 示例会记录触发 blob 的路径,包括容器:

public static void Run(string myBlob, string blobTrigger, ILogger log)
{
    log.LogInformation($"Full blob path: {blobTrigger}");
} 
module.exports = function (context, myBlob) {
    context.log("Full blob path:", context.bindingData.blobTrigger);
    context.done();
};

触发器 - Blob 回执

Azure Functions 运行时确保没有为相同的新 blob 或更新 blob 多次调用 blob 触发器函数。 为了确定是否已处理给定的 blob 版本,它会维护 blob 回执。

Azure Functions 将 Blob 回执存储在函数应用的 Azure 存储帐户中名为 azure-webjobs-hosts 的容器中(由 AzureWebJobsStorage 应用设置定义)。 Blob 回执包含以下信息:

  • 触发的函数("<function app name>.Functions.<function name>",例如:"MyFunctionApp.Functions.CopyBlob")
  • 容器名称
  • Blob 类型("BlockBlob" 或 "PageBlob")
  • Blob 名称
  • ETag(blob 版本标识符,例如:"0x8D1DC6E70A277EF")

若要强制重新处理某个 blob,可从 azure-webjobs-hosts 容器中手动删除该 blob 的 blob 回执。

触发器 - 有害 Blob

当给定 blob 的 blob 触发函数失败时,Azure Functions 将默认重试该函数共计 5 次。

如果 5 次尝试全部失败,Azure Functions 会将消息添加到名为 webjobs-blobtrigger-poison 的存储队列。 有害 Blob 的队列消息是包含以下属性的 JSON 对象:

  • FunctionId(格式为 <function app name>.Functions.<function name>)
  • BlobType("BlockBlob" 或 "PageBlob")
  • ContainerName
  • BlobName
  • ETag(blob 版本标识符,例如:"0x8D1DC6E70A277EF")

触发器 - 并发和内存使用情况

Blob 触发器可在内部使用队列,因此并发函数调用的最大数量受 host.json 中的队列配置控制。 默认设置会将并发限制到 24 个调用。 此限制分别应用于使用 blob 触发器的函数。

内存由每个并发执行函数实例和函数运行时本身使用。 如果 blob 触发的函数将整个 blob 加载到内存中,该函数使用的仅用于 blob 的最大内存为 24 * 最大 blob 大小。 例如,包含 3 个由 blob 触发的函数的函数应用和默认设置,其每 VM 最大并发为 3*24 = 72 个函数调用。

JavaScript 和 Java 函数会将整个 blob 加载到内存中,并且如果绑定到 stringByte[] 或 POCO,则 C# 函数也会如此。

触发器 - 轮询

如果受监视的 blob 容器包含 10,000 多个 blob,则 Functions 运行时将扫描日志文件,监视新的或更改的 blob。 此过程可能会导致延迟。 创建 blob 之后数分钟或更长时间内可能仍不会触发函数。 此外,将“尽力”创建存储日志。 不保证捕获所有事件。 在某些情况下可能会遗漏某些日志。 如果需要更快或更可靠的 blob 处理,在创建 blob 时,请考虑创建队列消息。 然后,使用队列触发器而不是 Blob 触发器来处理 Blob。

输入

使用 blob 存储输入绑定读取 blob。

输入 - 示例

参阅语言特定的示例:

输入 - C# 示例

以下示例演示使用一个队列触发器和一个 blob 输入绑定的 C# 函数。 队列消息包含该 blob 的名称,函数记录该 blob 的大小。

[FunctionName("BlobInput")]
public static void Run(
    [QueueTrigger("myqueue-items")] string myQueueItem,
    [Blob("samples-workitems/{queueTrigger}", FileAccess.Read)] Stream myBlob,
    ILogger log)
{
    log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
}

输入 - C# 脚本示例

以下示例演示 function.json 文件中的 blob 输入和输出绑定,以及使用这些绑定的 C# 脚本 (.csx) 代码。 此函数创建文本 blob 的副本。 该函数由包含要复制的 Blob 名称的队列消息触发。 新 Blob 名为 {originalblobname}-Copy

function.json 文件中,queueTrigger 元数据属性用于指定 path 属性中的 Blob 名称:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "myInputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "myOutputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}-Copy",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ],
  "disabled": false
}

配置部分解释了这些属性。

C# 脚本代码如下所示:

public static void Run(string myQueueItem, string myInputBlob, out string myOutputBlob, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
    myOutputBlob = myInputBlob;
}

输入 - JavaScript 示例

下面的示例展示了 function.json 文件中的 blob 输入和输出绑定,以及使用这些绑定的 JavaScript 代码。 该函数创建 Blob 的副本。 该函数由包含要复制的 Blob 名称的队列消息触发。 新 Blob 名为 {originalblobname}-Copy

function.json 文件中,queueTrigger 元数据属性用于指定 path 属性中的 Blob 名称:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "myInputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "myOutputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}-Copy",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ],
  "disabled": false
}

配置部分解释了这些属性。

JavaScript 代码如下所示:

module.exports = function(context) {
    context.log('Node.js Queue trigger function processed', context.bindings.myQueueItem);
    context.bindings.myOutputBlob = context.bindings.myInputBlob;
    context.done();
};

输入 - Python 示例

下面的示例展示了 function.json 文件中的 blob 输入和输出绑定,以及使用这些绑定的 Python 代码。 该函数创建 Blob 的副本。 该函数由包含要复制的 Blob 名称的队列消息触发。 新 Blob 名为 {originalblobname}-Copy

function.json 文件中,queueTrigger 元数据属性用于指定 path 属性中的 Blob 名称:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "queuemsg",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "inputblob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "$return",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}-Copy",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ],
  "disabled": false,
  "scriptFile": "__init__.py"
}

配置部分解释了这些属性。

下面是 Python 代码:

import logging
import azure.functions as func

def main(queuemsg: func.QueueMessage, inputblob: func.InputStream) -> func.InputStream:
    logging.info('Python Queue trigger function processed %s', inputblob.name)
    return inputblob

输入 - Java 示例

本部分包含以下示例:

HTTP 触发器,使用查询字符串查找 blob 名称 (Java)

下面的示例显示了一个 Java 函数,该函数使用 HttpTrigger 注释来接收包含 blob 存储容器中某个文件的名称的一个参数。 然后,BlobInput 注释读取该文件并将其作为 byte[] 传递给该函数。

  @FunctionName("getBlobSizeHttp")
  @StorageAccount("Storage_Account_Connection_String")
  public HttpResponseMessage blobSize(
    @HttpTrigger(name = "req", 
      methods = {HttpMethod.GET}, 
      authLevel = AuthorizationLevel.ANONYMOUS) 
    HttpRequestMessage<Optional<String>> request,
    @BlobInput(
      name = "file", 
      dataType = "binary", 
      path = "samples-workitems/{Query.file}") 
    byte[] content,
    final ExecutionContext context) {
      // build HTTP response with size of requested blob
      return request.createResponseBuilder(HttpStatus.OK)
        .body("The size of \"" + request.getQueryParameters().get("file") + "\" is: " + content.length + " bytes")
        .build();
  }

队列触发器,接收来自队列消息的 blob 名称 (Java)

下面的示例显示了一个 Java 函数,该函数使用 QueueTrigger 注释来接收包含 blob 存储容器中某个文件的名称的一个消息。 然后,BlobInput 注释读取该文件并将其作为 byte[] 传递给该函数。

  @FunctionName("getBlobSize")
  @StorageAccount("Storage_Account_Connection_String")
  public void blobSize(
    @QueueTrigger(
      name = "filename", 
      queueName = "myqueue-items-sample") 
    String filename,
    @BlobInput(
      name = "file", 
      dataType = "binary", 
      path = "samples-workitems/{queueTrigger}") 
    byte[] content,
    final ExecutionContext context) {
      context.getLogger().info("The size of \"" + filename + "\" is: " + content.length + " bytes");
  }

Java 函数运行时库中,对其值将来自 Blob 的参数使用 @BlobInput 注释。 可以将此注释与本机 Java 类型、POJO 或使用了 Optional<T> 的可为 null 的值一起使用。

输入 - 特性

C# 类库中,使用 BlobAttribute

该特性的构造函数采用 Blob 的路径,以及一个表示读取或写入的 FileAccess 参数,如以下示例中所示:

[FunctionName("BlobInput")]
public static void Run(
    [QueueTrigger("myqueue-items")] string myQueueItem,
    [Blob("samples-workitems/{queueTrigger}", FileAccess.Read)] Stream myBlob,
    ILogger log)
{
    log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
}

可以设置 Connection 属性来指定要使用的存储帐户,如以下示例中所示:

[FunctionName("BlobInput")]
public static void Run(
    [QueueTrigger("myqueue-items")] string myQueueItem,
    [Blob("samples-workitems/{queueTrigger}", FileAccess.Read, Connection = "StorageConnectionAppSetting")] Stream myBlob,
    ILogger log)
{
    log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
}

可以使用 StorageAccount 特性在类、方法或参数级别指定存储帐户。 有关详细信息,请参阅触发器 - 特性

输入 - 配置

下表解释了在 function.json 文件和 Blob 特性中设置的绑定配置属性。

function.json 属性 Attribute 属性 说明
类型 不适用 必须设置为 blob
direction 不适用 必须设置为 in用法部分中已阐述异常。
name 不适用 表示函数代码中的 Blob 的变量的名称。
路径 BlobPath Blob 的路径。
连接 Connection 包含要用于此绑定的存储连接字符串的应用设置的名称。 如果应用设置名称以“AzureWebJobs”开始,则只能在此处指定该名称的余下部分。 例如,如果将 connection 设置为“MyStorage”,函数运行时将会查找名为“AzureWebJobsMyStorage”的应用设置。 如果将 connection 留空,函数运行时将使用名为 AzureWebJobsStorage 的应用设置中的默认存储连接字符串。

连接字符串必须属于某个常规用途存储帐户,而不能属于仅限 Blob 的存储帐户
不适用 Access 表示是要读取还是写入。

在本地进行开发时,应用设置将取 local.settings.json 文件的值。

输入 - 用法

在 C# 和 C# 脚本中,可以为 blob 输入绑定使用以下参数类型:

  • Stream
  • TextReader
  • string
  • Byte[]
  • CloudBlobContainer
  • CloudBlobDirectory
  • ICloudBlob1
  • CloudBlockBlob1
  • CloudPageBlob1
  • CloudAppendBlob1

1 function.json 中需有 "inout" 绑定 direction 或 C# 类库中需有 FileAccess.ReadWrite

如果在尝试绑定到某个存储 SDK 类型时出现错误消息,请确保引用正确的存储 SDK 版本

由于整个 Blob 内容都会加载到内存中,因此,只有当 Blob 较小时才建议绑定到 stringByte[]。 平时,最好使用 StreamCloudBlockBlob 类型。 有关详细信息,请参阅本文前文中的并发和内存使用情况

在 JavaScript 中,可以使用 context.bindings.<name from function.json> 访问 Blob 数据。

输出

使用 blob 存储输出绑定写入 blob。

输出 - 示例

参阅语言特定的示例:

输出 - C# 示例

以下示例演示使用一个 blob 触发器和两个 blob 输出绑定的 C# 函数。 在 sample-images 容器中创建映像 Blob 时,会触发该函数。 该函数创建该映像 Blob 的小型和中型副本。

[FunctionName("ResizeImage")]
public static void Run(
    [BlobTrigger("sample-images/{name}")] Stream image,
    [Blob("sample-images-sm/{name}", FileAccess.Write)] Stream imageSmall,
    [Blob("sample-images-md/{name}", FileAccess.Write)] Stream imageMedium)
{
    var imageBuilder = ImageResizer.ImageBuilder.Current;
    var size = imageDimensionsTable[ImageSize.Small];

    imageBuilder.Build(image, imageSmall,
        new ResizeSettings(size.Item1, size.Item2, FitMode.Max, null), false);

    image.Position = 0;
    size = imageDimensionsTable[ImageSize.Medium];

    imageBuilder.Build(image, imageMedium,
        new ResizeSettings(size.Item1, size.Item2, FitMode.Max, null), false);
}

public enum ImageSize { ExtraSmall, Small, Medium }

private static Dictionary<ImageSize, (int, int)> imageDimensionsTable = new Dictionary<ImageSize, (int, int)>() {
    { ImageSize.ExtraSmall, (320, 200) },
    { ImageSize.Small,      (640, 400) },
    { ImageSize.Medium,     (800, 600) }
};

输出 - C# 脚本示例

以下示例演示 function.json 文件中的 blob 输入和输出绑定,以及使用这些绑定的 C# 脚本 (.csx) 代码。 此函数创建文本 blob 的副本。 该函数由包含要复制的 Blob 名称的队列消息触发。 新 Blob 名为 {originalblobname}-Copy

function.json 文件中,queueTrigger 元数据属性用于指定 path 属性中的 Blob 名称:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "myInputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "myOutputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}-Copy",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ],
  "disabled": false
}

配置部分解释了这些属性。

C# 脚本代码如下所示:

public static void Run(string myQueueItem, string myInputBlob, out string myOutputBlob, ILogger log)
{
    log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
    myOutputBlob = myInputBlob;
}

输出 - JavaScript 示例

下面的示例展示了 function.json 文件中的 blob 输入和输出绑定,以及使用这些绑定的 JavaScript 代码。 该函数创建 Blob 的副本。 该函数由包含要复制的 Blob 名称的队列消息触发。 新 Blob 名为 {originalblobname}-Copy

function.json 文件中,queueTrigger 元数据属性用于指定 path 属性中的 Blob 名称:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "myInputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "myOutputBlob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}-Copy",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ],
  "disabled": false
}

配置部分解释了这些属性。

JavaScript 代码如下所示:

module.exports = function(context) {
    context.log('Node.js Queue trigger function processed', context.bindings.myQueueItem);
    context.bindings.myOutputBlob = context.bindings.myInputBlob;
    context.done();
};

输出 - Python 示例

下面的示例展示了 function.json 文件中的 blob 输入和输出绑定,以及使用这些绑定的 Python 代码。 该函数创建 Blob 的副本。 该函数由包含要复制的 Blob 名称的队列消息触发。 新 Blob 名为 {originalblobname}-Copy

function.json 文件中,queueTrigger 元数据属性用于指定 path 属性中的 Blob 名称:

{
  "bindings": [
    {
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting",
      "name": "queuemsg",
      "type": "queueTrigger",
      "direction": "in"
    },
    {
      "name": "inputblob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "outputblob",
      "type": "blob",
      "path": "samples-workitems/{queueTrigger}-Copy",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ],
  "disabled": false,
  "scriptFile": "__init__.py"
}

配置部分解释了这些属性。

下面是 Python 代码:

import logging
import azure.functions as func

def main(queuemsg: func.QueueMessage, inputblob: func.InputStream,
         outputblob: func.Out[func.InputStream]):
    logging.info('Python Queue trigger function processed %s', inputblob.name)
    outputblob.set(inputblob)

输出 - Java 示例

本部分包含以下示例:

HTTP 触发器,使用 OutputBinding (Java)

下面的示例显示了一个 Java 函数,该函数使用 HttpTrigger 注释来接收包含 blob 存储容器中某个文件的名称的一个参数。 然后,BlobInput 注释读取该文件并将其作为 byte[] 传递给该函数。 BlobOutput 注释绑定到 OutputBinding outputItem,然后,函数使用后者来将输入 blob 的内容写入到所配置的存储容器中。

  @FunctionName("copyBlobHttp")
  @StorageAccount("Storage_Account_Connection_String")
  public HttpResponseMessage copyBlobHttp(
    @HttpTrigger(name = "req", 
      methods = {HttpMethod.GET}, 
      authLevel = AuthorizationLevel.ANONYMOUS) 
    HttpRequestMessage<Optional<String>> request,
    @BlobInput(
      name = "file", 
      dataType = "binary", 
      path = "samples-workitems/{Query.file}") 
    byte[] content,
    @BlobOutput(
      name = "target", 
      path = "myblob/{Query.file}-CopyViaHttp")
    OutputBinding<String> outputItem,
    final ExecutionContext context) {
      // Save blob to outputItem
      outputItem.setValue(new String(content, StandardCharsets.UTF_8));

      // build HTTP response with size of requested blob
      return request.createResponseBuilder(HttpStatus.OK)
        .body("The size of \"" + request.getQueryParameters().get("file") + "\" is: " + content.length + " bytes")
        .build();
  }

队列触发器,使用函数返回值 (Java)

下面的示例显示了一个 Java 函数,该函数使用 QueueTrigger 注释来接收包含 blob 存储容器中某个文件的名称的一个消息。 然后,BlobInput 注释读取该文件并将其作为 byte[] 传递给该函数。 BlobOutput 注释绑定到函数返回值,然后,运行时使用后者来将输入 blob 的内容写入到所配置的存储容器中。

  @FunctionName("copyBlobQueueTrigger")
  @StorageAccount("Storage_Account_Connection_String")
  @BlobOutput(
    name = "target", 
    path = "myblob/{queueTrigger}-Copy")
  public String copyBlobQueue(
    @QueueTrigger(
      name = "filename", 
      dataType = "string",
      queueName = "myqueue-items") 
    String filename,
    @BlobInput(
      name = "file", 
      path = "samples-workitems/{queueTrigger}") 
    String content,
    final ExecutionContext context) {
      context.getLogger().info("The content of \"" + filename + "\" is: " + content);
      return content;
  }

Java 函数运行时库中,对其值将写入 Blob 存储中对象的函数参数使用 @BlobOutput 注释。 参数类型应为 OutputBinding<T>,其中 T 是任何本机 Java 类型或者是一个 POJO。

输出 - 特性

C# 类库中,使用 BlobAttribute

该特性的构造函数采用 Blob 的路径,以及一个表示读取或写入的 FileAccess 参数,如以下示例中所示:

[FunctionName("ResizeImage")]
public static void Run(
    [BlobTrigger("sample-images/{name}")] Stream image,
    [Blob("sample-images-md/{name}", FileAccess.Write)] Stream imageSmall)
{
    ...
}

可以设置 Connection 属性来指定要使用的存储帐户,如以下示例中所示:

[FunctionName("ResizeImage")]
public static void Run(
    [BlobTrigger("sample-images/{name}")] Stream image,
    [Blob("sample-images-md/{name}", FileAccess.Write, Connection = "StorageConnectionAppSetting")] Stream imageSmall)
{
    ...
}

有关完整示例,请参阅输出 - C# 示例

可以使用 StorageAccount 特性在类、方法或参数级别指定存储帐户。 有关详细信息,请参阅触发器 - 特性

输出 - 配置

下表解释了在 function.json 文件和 Blob 特性中设置的绑定配置属性。

function.json 属性 Attribute 属性 说明
类型 不适用 必须设置为 blob
direction 不适用 对于输出绑定,必须设置为 out用法部分中已阐述异常。
name 不适用 表示函数代码中的 Blob 的变量的名称。 设置为 $return 可引用函数返回值。
路径 BlobPath Blob 的路径。
连接 Connection 包含要用于此绑定的存储连接字符串的应用设置的名称。 如果应用设置名称以“AzureWebJobs”开始,则只能在此处指定该名称的余下部分。 例如,如果将 connection 设置为“MyStorage”,函数运行时将会查找名为“AzureWebJobsMyStorage”的应用设置。 如果将 connection 留空,函数运行时将使用名为 AzureWebJobsStorage 的应用设置中的默认存储连接字符串。

连接字符串必须属于某个常规用途存储帐户,而不能属于仅限 Blob 的存储帐户
不适用 Access 表示是要读取还是写入。

在本地进行开发时,应用设置将取 local.settings.json 文件的值。

输出 - 用法

在 C# 和 C# 脚本中,可绑定到以下类型,以编写 blob:

  • TextWriter
  • out string
  • out Byte[]
  • CloudBlobStream
  • Stream
  • CloudBlobContainer1
  • CloudBlobDirectory
  • ICloudBlob2
  • CloudBlockBlob2
  • CloudPageBlob2
  • CloudAppendBlob2

1 function.json 中需有 "in" 绑定 direction 或 C# 类库中需有 FileAccess.Read。 但是,可以使用运行时提供的容器对象来执行写入操作,例如将 Blob 上传到容器。

2 function.json 中需有 "inout" 绑定 direction 或 C# 类库中需有 FileAccess.ReadWrite

如果在尝试绑定到某个存储 SDK 类型时出现错误消息,请确保引用正确的存储 SDK 版本

在异步函数中,请使用返回值或 IAsyncCollector 而非 out 参数。

由于整个 Blob 内容都会加载到内存中,因此,只有当 Blob 较小时才建议绑定到 stringByte[]。 平时,最好使用 StreamCloudBlockBlob 类型。 有关详细信息,请参阅本文前文中的并发和内存使用情况

在 JavaScript 中,可以使用 context.bindings.<name from function.json> 访问 Blob 数据。

异常和返回代码

绑定 参考
Blob Blob 错误代码
Blob、表、队列 存储错误代码
Blob、表、队列 故障排除

后续步骤