适用于 Azure Functions 的 Azure Blob 存储触发器
检测到新的或更新的 Blob 时,Blob 存储触发器会启动某个函数。 Blob 内容以函数输入的形式提供。
提示
根据存储容器中 blob 的更改,可通过多种方法执行函数代码。 如果选择使用 Blob 存储触发器,注意这里提供了两个实现:基于轮询的实现(即本文引用的实现)和基于事件的实现。 建议使用基于事件的实现,因为它的延迟比其他实现低。 此外,Flex 消耗计划仅支持基于事件的 Blob 存储触发器。
如需详细了解 Blob 存储触发器的两个实现之间的差异以及其他触发选项,请参阅使用 Blob。
有关设置和配置详细信息,请参阅概述。
重要
本文使用选项卡来支持多个版本的 Node.js 编程模型。 v4 模型目前处于预览状态,旨在为 JavaScript 和 TypeScript 开发人员提供更为灵活和直观的体验。 在升级指南中详细了解 v3 和 v4 之间的差异。
重要
本文使用选项卡来支持多个版本的 Python 编程模型。 v2 模型已正式发布,旨在提供一种更加以代码为中心的方法,用于通过修饰器创作函数。 有关 v2 模型工作原理的更多详细信息,请参阅 Azure Functions Python 开发人员指南。
示例
可以使用以下 C# 模式之一创建 C# 函数:
- 进程内类库:编译的 C# 函数,该函数在与 Functions 运行时相同的进程中运行。
- 独立进程类库:编译的 C# 函数,该函数在独立于运行时的进程中运行。 支持在 .NET 5.0 上运行的 C# 函数需要独立的进程。
- C# 脚本:主要在 Azure 门户中创建 C# 函数时使用。
重要
对进程内模型的支持将于 2026 年 11 月 10 日结束。 为获得完全支持,强烈建议将应用迁移到独立工作模型。
以下示例是一个 C# 函数,该函数在独立工作进程中运行,并将 blob 触发器与 blob 输入和 blob 输出 blob 绑定配合使用。 在 test-samples-trigger 容器中创建 blob 时,会触发该函数。 它从 test-samples-input 容器读取文本文件,并基于已触发文件的名称在输出容器中创建一个新的文本文件。
public static class BlobFunction
{
[Function(nameof(BlobFunction))]
[BlobOutput("test-samples-output/{name}-output.txt")]
public static string Run(
[BlobTrigger("test-samples-trigger/{name}")] string myTriggerItem,
[BlobInput("test-samples-input/sample1.txt")] string myBlob,
FunctionContext context)
{
var logger = context.GetLogger("BlobFunction");
logger.LogInformation("Triggered Item = {myTriggerItem}", myTriggerItem);
logger.LogInformation("Input Item = {myBlob}", myBlob);
// Blob Output
return "blob-output content";
}
}
在 myblob
容器中添加或更新 Blob 时,该函数会写入一条日志。
@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");
}
以下示例显示 blob 触发器 TypeScript 代码。 在 samples-workitems
容器中添加或更新 Blob 时,该函数会写入日志。
blob 触发器路径 samples-workitems/{name}
中的字符串 {name}
会创建一个绑定表达式,可以在函数代码中使用它来访问触发 blob 的文件名。 有关详细信息,请参阅本文下文中的 Blob 名称模式。
import { app, InvocationContext } from '@azure/functions';
export async function storageBlobTrigger1(blob: Buffer, context: InvocationContext): Promise<void> {
context.log(
`Storage blob function processed blob "${context.triggerMetadata.name}" with size ${blob.length} bytes`
);
}
app.storageBlob('storageBlobTrigger1', {
path: 'samples-workitems/{name}',
connection: 'MyStorageAccountAppSetting',
handler: storageBlobTrigger1,
});
以下示例显示 blob 触发器 JavaScript 代码。 在 samples-workitems
容器中添加或更新 Blob 时,该函数会写入日志。
blob 触发器路径 samples-workitems/{name}
中的字符串 {name}
会创建一个绑定表达式,可以在函数代码中使用它来访问触发 blob 的文件名。 有关详细信息,请参阅本文下文中的 Blob 名称模式。
const { app } = require('@azure/functions');
app.storageBlob('storageBlobTrigger1', {
path: 'samples-workitems/{name}',
connection: 'MyStorageAccountAppSetting',
handler: (blob, context) => {
context.log(
`Storage blob function processed blob "${context.triggerMetadata.name}" with size ${blob.length} bytes`
);
},
});
下面的示例演示如何创建在将文件添加到 source
blob 存储容器时运行的函数。
函数配置文件 (function.json) 包含一个绑定,其 type
为 blobTrigger
且 direction
设置为 in
。
{
"bindings": [
{
"name": "InputBlob",
"type": "blobTrigger",
"direction": "in",
"path": "source/{name}",
"connection": "MyStorageAccountConnectionString"
}
]
}
下面是 run.ps1 文件的关联代码。
param([byte[]] $InputBlob, $TriggerMetadata)
Write-Host "PowerShell Blob trigger: Name: $($TriggerMetadata.Name) Size: $($InputBlob.Length) bytes"
此示例使用 SDK 类型直接访问 Blob 存储触发器提供的基础 BlobClient
对象:
import logging
import azure.functions as func
import azurefunctions.extensions.bindings.blob as blob
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
@app.blob_trigger(
arg_name="client", path="PATH/TO/BLOB", connection="AzureWebJobsStorage"
)
def blob_trigger(client: blob.BlobClient):
logging.info(
f"Python blob trigger function processed blob \n"
f"Properties: {client.get_blob_properties()}\n"
f"Blob content head: {client.download_blob().read(size=1)}"
)
有关使用其他 SDK 类型的示例,请参阅 ContainerClient
和 StorageStreamDownloader
示例。
若要了解详细信息,包括如何在项目中启用 SDK 类型绑定,请参阅 SDK 类型绑定。
此示例记录传入 Blob 元数据中的信息。
import logging
import azure.functions as func
app = func.FunctionApp()
@app.function_name(name="BlobTrigger1")
@app.blob_trigger(arg_name="myblob",
path="PATH/TO/BLOB",
connection="CONNECTION_SETTING")
def test_function(myblob: func.InputStream):
logging.info(f"Python blob trigger function processed blob \n"
f"Name: {myblob.name}\n"
f"Blob Size: {myblob.length} bytes")
特性
进程内和独立工作进程 C# 库都使用 BlobAttribute 特性来定义函数。 C# 脚本改用 function.json 配置文件,如 C# 脚本指南中所述。
该特性的构造函数采用以下参数:
参数 | 说明 |
---|---|
BlobPath | Blob 的路径。 |
Connection | 指定如何连接到 Azure Blob 的应用设置或设置集合的名称。 请参阅连接。 |
访问 | 表示是要读取还是写入。 |
Source | 设置触发事件的源。 将 BlobTriggerSource.EventGrid 用于基于事件网格的 Blob 触发器,这样可以显著缩短延迟。 默认值为 BlobTriggerSource.LogsAndContainerScan ,它使用标准轮询机制来检测容器中的更改。 |
下面是某个方法签名中的 BlobTrigger
特性:
[Function(nameof(BlobFunction))]
[BlobOutput("test-samples-output/{name}-output.txt")]
public static string Run(
[BlobTrigger("test-samples-trigger/{name}")] string myTriggerItem,
[BlobInput("test-samples-input/sample1.txt")] string myBlob,
FunctionContext context)
在本地开发时,需要将应用程序设置添加到 Values
集合中的 local.settings.json 文件中。
修饰符
仅适用于 Python v2 编程模型。
对于使用修饰器定义的 Python v2 函数,blob_trigger
修饰器上的以下属性可定义 Blob 存储触发器:
properties | 说明 |
---|---|
arg_name |
在函数签名中声明参数名称。 触发函数时,此参数的值包含队列消息的内容。 |
path |
要监视的容器。 可以是某种 Blob 名称模式。 |
connection |
存储帐户连接字符串。 |
source |
设置触发事件的源。 将 EventGrid 用于基于事件网格的 Blob 触发器,这样可以显著缩短延迟。 默认值为 LogsAndContainerScan ,该机制使用标准轮询机制检测容器中的更改。 |
对于使用 function.json 定义的 Python 函数,请参阅“配置”部分。
批注
@BlobTrigger
特性用于授予对触发函数的 blob 的访问权限。 有关详细信息,请参阅触发器示例。 使用 source
属性设置触发事件的源。 将 EventGrid
用于基于事件网格的 Blob 触发器,这样可以显著缩短延迟。 默认值为 LogsAndContainerScan
,该机制使用标准轮询机制检测容器中的更改。 |
配置
仅适用于 Python v1 编程模型。
下表解释了在 function.json 文件中设置的绑定配置属性。
“function.json”属性 | 说明 |
---|---|
type | 必须设置为 blobTrigger 。 在 Azure 门户中创建触发器时,会自动设置此属性。 |
direction | 必须设置为 in 。 在 Azure 门户中创建触发器时,会自动设置此属性。 用法部分中已阐述异常。 |
name | 表示函数代码中的 Blob 的变量的名称。 |
路径 | 要监视的容器。 可以是某种 Blob 名称模式。 |
连接 | 指定如何连接到 Azure Blob 的应用设置或设置集合的名称。 请参阅连接。 |
源 | 设置触发事件的源。 将 EventGrid 用于基于事件网格的 Blob 触发器,这样可以显著缩短延迟。 默认值为 LogsAndContainerScan ,该机制使用标准轮询机制检测容器中的更改。 |
有关完整示例的信息,请参阅示例部分。
Metadata
Blob 触发器提供了几个元数据属性。 这些属性可在其他绑定中用作绑定表达式的一部分,或者用作代码中的参数。 这些值具有与 CloudBlob 类型相同的语义。
属性 | 类型 | 说明 |
---|---|---|
BlobTrigger |
string |
触发 Blob 的路径。 |
Uri |
System.Uri |
主位置的 blob 的 URI。 |
Properties |
BlobProperties | Blob 的系统属性。 |
Metadata |
IDictionary<string,string> |
Blob 的用户定义元数据。 |
以下示例记录了触发 blob 的路径,包括容器:
public static void Run(string myBlob, string blobTrigger, ILogger log)
{
log.LogInformation($"Full blob path: {blobTrigger}");
}
Metadata
Blob 触发器提供了几个元数据属性。 这些属性可在其他绑定中用作绑定表达式的一部分,或者用作代码中的参数。
属性 | 说明 |
---|---|
blobTrigger |
触发 Blob 的路径。 |
uri |
主位置的 blob 的 URI。 |
properties |
Blob 的系统属性。 |
metadata |
Blob 的用户定义元数据。 |
Metadata
可以通过 $TriggerMetadata
参数获取元数据。
使用情况
Blob 触发器支持的绑定类型取决于函数应用中使用的扩展包版本和 C# 形式。
Blob 触发器可以绑定到以下类型:
类型 | 说明 |
---|---|
string |
Blob 内容即字符串。 在 blob 内容为简单文本时使用。 |
byte[] |
Blob 内容的字节数。 |
JSON 可序列化类型 | 当 blob 包含 JSON 数据时,Functions 会尝试将 JSON 数据反序列化为普通的旧 CLR 对象 (POCO) 类型。 |
流 | (预览版1) Blob 内容的输入流。 |
BlobClient, BlockBlobClient, PageBlobClient, AppendBlobClient, BlobBaseClient |
(预览版1) 连接到 blob 的客户端。 这提供了对 blob 处理的充分控制,如果连接具有足够的权限,则可用于写回 blob。 |
1 若要使用这些类型,需要引用 Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 5.1.1-preview2 或更高版本以及 SDK 类型绑定的常见依赖项。
仅当 blob 大小较小时才建议绑定到 string
或 Byte[]
。 我们推荐此做法,因为整个 blob 内容都会加载到内存中。 对于大多数 blob,请使用 Stream
或 BlobClient
类型。 有关详细信息,请参阅并发和内存使用情况。
如果尝试绑定到某个存储 SDK 类型时收到了错误消息,请确保已引用正确的存储 SDK 版本。
还可使用 StorageAccountAttribute 指定要使用的存储帐户。 如果需要使用一个不同于库中的其他函数的存储帐户,可以执行此操作。 构造函数采用包含存储连接字符串的应用设置的名称。 可以在参数、方法或类级别应用该特性。 以下示例演示类级别和方法级别:
[StorageAccount("ClassLevelStorageAppSetting")]
public static class AzureFunctions
{
[FunctionName("BlobTrigger")]
[StorageAccount("FunctionLevelStorageAppSetting")]
public static void Run( //...
{
....
}
要使用的存储帐户按以下顺序确定:
BlobTrigger
特性的Connection
属性。- 作为
BlobTrigger
特性应用到同一参数的StorageAccount
特性。 - 应用到函数的
StorageAccount
特性。 - 应用到类的
StorageAccount
特性。 - 函数应用的默认存储帐户,在
AzureWebJobsStorage
应用程序设置中定义。
@BlobTrigger
特性用于授予对触发函数的 blob 的访问权限。 有关详细信息,请参阅触发器示例。
通过与 function.json 文件中绑定名称参数指定的名称匹配的字符串参数访问 Blob 数据。
通过类型为 InputStream 的参数访问 blob 数据。 有关详细信息,请参阅触发器示例。
Functions 还支持用于 Azure Blob 存储的 Python SDK 类型绑定,这样便可以使用以下基础 SDK 类型处理 Blob 数据:
重要
对 Python 的 SDK 类型支持目前为预览版,并且仅支持 Python v2 编程模型。 有关详细信息,请参阅 Python 中的 SDK 类型。
连接
connection
属性是对环境配置的引用,它指定应用应如何连接到 Azure Blob。 它可能指定:
如果配置的值既是单个设置的完全匹配,也是其他设置的前缀匹配,则使用完全匹配。
连接字符串
要获取连接字符串,请执行管理存储帐户访问密钥中显示的步骤。 连接字符串必须属于某个常规用途存储帐户,而不能属于Blob 存储帐户。
此连接字符串应存储在应用程序设置中,其名称与绑定配置的 connection
属性指定的值匹配。
如果应用设置名称以“AzureWebJobs”开始,则只能在此处指定该名称的余下部分。 例如,如果将 connection
设置为“MyStorage”,则 Functions 运行时会查找名为“AzureWebJobsMyStorage”的应用设置。 如果将 connection
留空,函数运行时将使用名为 AzureWebJobsStorage
的应用设置中的默认存储连接字符串。
基于标识的连接
如果使用 5.x 或更高版本的扩展,则无需将连接字符串与机密配合使用,可以让应用使用 Azure Active Directory 标识。 要使用标识,需要定义公共前缀下的设置,该前缀映射到触发器和绑定配置中的 connection
属性。
如果将 connection
设置为“AzureWebJobsStorage”,请参阅使用标识连接到主机存储。 对于所有其他连接,扩展需要以下属性:
属性 | 环境变量模板 | 说明 | 示例值 |
---|---|---|---|
Blob 服务 URI | <CONNECTION_NAME_PREFIX>__serviceUri 1 |
要连接到的 Blob 服务的数据平面 URI,使用 HTTPS 方案。 | https://<storage_account_name>.blob.core.chinacloudapi.cn |
1 <CONNECTION_NAME_PREFIX>__blobServiceUri
可以用作别名。 如果连接配置将由 Blob 触发器使用,则 blobServiceUri
还必须带有 queueServiceUri
。 请参阅下文。
如果要跨 Blob、队列和/或表使用总体连接配置,则无法使用 serviceUri
窗体。 URI 只能指定 Blob 服务。 作为一种替代方案,可以为每个服务专门提供一个 URI,从而允许使用单个连接。 如果这两个版本均提供,则将使用多服务窗体。 若要为多个服务(而不是 <CONNECTION_NAME_PREFIX>__serviceUri
)配置连接,请设置:
属性 | 环境变量模板 | 说明 | 示例值 |
---|---|---|---|
Blob 服务 URI | <CONNECTION_NAME_PREFIX>__blobServiceUri |
要连接到的 Blob 服务的数据平面 URI,使用 HTTPS 方案。 | https://<storage_account_name>.blob.core.chinacloudapi.cn |
队列服务 URI(Blob 触发器需要2) | <CONNECTION_NAME_PREFIX>__queueServiceUri |
使用 HTTPS 方案的队列服务的数据平面 URI。 仅 Blob 触发器需要该值。 | https://<storage_account_name>.queue.core.chinacloudapi.cn |
2 Blob 触发器通过将有害 blob 写入队列来处理多次重试中出现的故障。 在 serviceUri
窗体中,将使用 AzureWebJobsStorage
连接。 但是,在指定 blobServiceUri
时,还必须为 queueServiceUri
提供队列服务 URI。 建议使用与 Blob 服务相同的存储帐户中的服务。 还需要通过分配存储队列数据参与者等角色来确保触发器可以在配置的队列服务中读取和写入消息。
可以设置其他属性来自定义连接。 请参阅基于标识的连接的通用属性。
在 Azure Functions 服务中托管时,基于标识的连接将使用托管标识。 默认情况下使用系统分配的标识,但可以使用 credential
和 clientID
属性来指定用户分配的标识。 请注意,不支持为用户分配的标识配置资源 ID。 在其他上下文(如本地开发)中运行时,将改用开发人员标识,尽管可以进行自定义。 请参阅使用基于标识的连接进行本地开发。
向标识授予权限
无论使用何种标识,都必须具有执行所需操作的权限。 需要使用内置角色或者提供这些权限的自定义角色在 Azure RBAC 中分配角色。
重要
某些权限可能由并非所有上下文都需要的目标服务公开。 尽可能遵循最低权限原则,仅授予标识所需的权限。 例如,如果应用只需要从数据源进行读取即可,则使用仅具有读取权限的角色。 分配一个也具有该服务写入权限的角色并不恰当,因为对于读取操作来说,写入是多余的权限。 同样,你也希望确保角色分配的范围仅限于需要读取的资源。
你需要创建一个角色分配,以在运行时提供对 Blob 容器的访问权限。 所有者等管理角色还不够。 下表显示了在正常操作中使用 Blob 存储扩展时建议使用的内置角色。 根据所编写的代码,应用程序可能需要进一步的权限。
绑定类型 | 内置角色示例 |
---|---|
触发器 | 存储 Blob 数据所有者和存储队列数据参与者1 此外,还必须向 AzureWebJobsStorage 连接授予额外的权限。2 |
输入绑定 | 存储 Blob 数据读者 |
输出绑定 | 存储 Blob 数据所有者 |
1 Blob 触发器通过将有害 blob 写入到连接所指定的存储帐户上的队列来处理多次重试中出现的故障。
2 AzureWebJobsStorage 连接在内部用于启用触发器的 blob 和队列。 如果将其配置为使用基于标识的连接,则该连接将需要超出默认要求的其他权限。 存储 Blob 数据所有者、存储队列数据参与者和存储帐户参与者角色涵盖了所需的权限。 若要了解更多信息,请参阅使用标识连接到主机存储。
Blob 名称模式
可以在 function.json 的 path
属性中或者在 BlobTrigger
特性构造函数中指定 Blob 名称模式。 名称模式可以是筛选器或绑定表达式。 以下部分提供了有关示例。
提示
容器名称不能在名称模式中包含解析程序。
获取文件名和扩展名
以下示例演示如何分别绑定到 Blob 文件名和扩展名:
"path": "input/{blobname}.{blobextension}",
如果 Blob 名为 original-Blob1.txt,则函数代码中 blobname
和 blobextension
变量的值为 original-Blob1 和 txt。
按 Blob 名称筛选
以下示例仅根据 input
容器中以字符串“original-”开头的 Blob 触发:
"path": "input/original-{name}",
如果 Blob 名称为 original-Blob1.txt,则函数代码中 name
变量的值为 Blob1.txt
。
按文件类型筛选
以下示例仅根据 .png 文件触发:
"path": "samples/{name}.png",
按文件名中的大括号筛选
若要查找文件名中的大括号,请使用两个大括号将大括号转义。 以下示例筛选名称中包含大括号的 Blob:
"path": "images/{{20140101}}-{name}",
如果 Blob 名为 {20140101}-soundfile.mp3,则函数代码中的 name
变量值为 soundfile.mp3。
轮询和延迟
轮询在检查日志和运行定期容器扫描之间起到混合作用。 每次以 10,000 个为一组扫描 Blob,并在间隔之间使用继续标记。 如果函数应用基于消耗计划,则当函数应用处于空闲状态时,处理新 Blob 会出现长达 10 分钟的延迟。
警告
存储日志将基于“尽力而为”的准则创建。 不保证捕获所有事件。 在某些情况下可能会遗漏某些日志。
如果需要更快或更可靠的 blob 处理,应考虑切换托管以使用启用了 Always On 的应用服务计划,这可能会导致成本增加。 还可考虑使用经典轮询 blob 触发器以外的触发器。 有关详细信息及 blob 存储容器的各种触发选项的比较,请参阅 blob 容器上的触发器。
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 回执。 虽然重新处理可能不会立即发生,但它肯定会在稍后的时间点发生。 若要立即重新处理,可以更新 azure-webjobs-hosts/blobscaninfo 中的 scaninfo Blob 。 将再次扫描 LatestScan
属性后具有上次修改时间戳的任何 Blob。
有害 Blob
当给定 blob 的 blob 触发函数失败时,Azure Functions 将默认重试该函数共计 5 次。
如果 5 次尝试全部失败,Azure Functions 会将消息添加到名为 webjobs-blobtrigger-poison 的存储队列。 最大尝试次数可配置。 使用相同的 MaxDequeueCount 设置处理有害 Blob 和有害队列消息。 有害 Blob 的队列消息是包含以下属性的 JSON 对象:
- FunctionId(格式为
<FUNCTION_APP_NAME>.Functions.<FUNCTION_NAME>
) - BlobType(
BlockBlob
或PageBlob
) - ContainerName
- BlobName
- ETag(blob 版本标识符,例如:
0x8D1DC6E70A277EF
)
内存使用率和并发性
绑定到不支持流式处理的输出类型(例如 string
或 Byte[]
)时,运行时必须在处理期间将整个 Blob 多次加载到内存中。 这可能会导致处理 Blob 时内存使用率高于预期。 如果可能,请使用支持流的类型。 类型支持取决于 C# 模式和扩展版本。 有关详细信息,请参阅绑定类型。
此时,运行时必须在处理期间将整个 Blob 多次加载到内存中。 这可能会导致处理 Blob 时内存使用率高于预期。
当多个函数实例同时处理 Blob 数据时,内存使用率可能会进一步受到影响。 如果使用 Blob 触发器遇到内存问题,请考虑减少允许的并发执行数。 当然,减少并发可能会产生增加等待处理的 blob 积压的副作用。 函数应用的内存限制取决于计划。 有关详细信息,请参阅服务限制。
可以控制并发执行数的方式取决于所使用的存储扩展的版本。
使用存储扩展版本 5.0.0 或更高版本时,可以使用 host.json 的 blob 配置中的 maxDegreeOfParallelism
设置来控制触发并发。
限制分别应用于使用 blob 触发器的每个函数。
host.json 属性
host.json 文件包含控制 blob 触发器行为的设置。 有关可用设置的详细信息,请参阅 host.json 设置部分。