Skip to content

Commit 5507582

Browse files
Merge pull request #104262 from craigshoemaker/crs-functions-binding-restructure-blob
Restructure blob storage binding reference
2 parents dac58b7 + d0972ae commit 5507582

18 files changed

+1227
-1175
lines changed

articles/azure-functions/TOC.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,15 @@
327327
- name: Triggers and bindings
328328
items:
329329
- name: Blob storage
330-
href: functions-bindings-storage-blob.md
330+
items:
331+
- name: Overview
332+
href: functions-bindings-storage-blob.md
333+
- name: Trigger
334+
href: functions-bindings-storage-blob-trigger.md
335+
- name: Input
336+
href: functions-bindings-storage-blob-input.md
337+
- name: Output
338+
href: functions-bindings-storage-blob-output.md
331339
- name: Azure Cosmos DB
332340
items:
333341
- name: Functions 1.x

articles/azure-functions/durable/durable-functions-dotnet-entities.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ public static Task Run([EntityTrigger] IDurableEntityContext ctx)
367367

368368
Unlike regular functions, entity class methods don't have direct access to input and output bindings. Instead, binding data must be captured in the entry-point function declaration and then passed to the `DispatchAsync<T>` method. Any objects passed to `DispatchAsync<T>` will be automatically passed into the entity class constructor as an argument.
369369

370-
The following example shows how a `CloudBlobContainer` reference from the [blob input binding](../functions-bindings-storage-blob.md#input) can be made available to a class-based entity.
370+
The following example shows how a `CloudBlobContainer` reference from the [blob input binding](../functions-bindings-storage-blob-input.md) can be made available to a class-based entity.
371371

372372
```csharp
373373
public class BlobBackedEntity

articles/azure-functions/functions-add-output-binding-storage-queue-java.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ mvn azure-functions:run
113113
```
114114

115115
> [!NOTE]
116-
> Because you enabled extension bundles in the host.json, the [Storage binding extension](functions-bindings-storage-blob.md#packages---functions-2x-and-higher) was downloaded and installed for you during startup, along with the other Microsoft binding extensions.
116+
> Because you enabled extension bundles in the host.json, the [Storage binding extension](functions-bindings-storage-blob.md#add-to-your-functions-app) was downloaded and installed for you during startup, along with the other Microsoft binding extensions.
117117
118118
As before, trigger the function from the command line using cURL in a new terminal window:
119119

articles/azure-functions/functions-add-output-binding-storage-queue-python.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ Observe that you *don't* need to write any code for authentication, getting a qu
151151
1. When you're done, stop the host with **Ctrl**+**C**.
152152
153153
> [!TIP]
154-
> During startup, the host downloads and installs the [Storage binding extension](functions-bindings-storage-blob.md#packages---functions-2x-and-higher) and other Microsoft binding extensions. This installation happens because binding extensions are enabled by default in the *host.json* file with the following properties:
154+
> During startup, the host downloads and installs the [Storage binding extension](functions-bindings-storage-blob.md#add-to-your-functions-app) and other Microsoft binding extensions. This installation happens because binding extensions are enabled by default in the *host.json* file with the following properties:
155155
>
156156
> ```json
157157
> {

articles/azure-functions/functions-bindings-error-pages.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ When integrating with Azure services, errors may originate from the APIs of the
2424

2525
+ [Azure Cosmos DB](functions-bindings-cosmosdb.md#exceptions-and-return-codes)
2626

27-
+ [Blob storage](functions-bindings-storage-blob.md#exceptions-and-return-codes)
27+
+ [Blob storage](functions-bindings-storage-blob-output.md#exceptions-and-return-codes)
2828

2929
+ [Event Hubs](functions-bindings-event-hubs.md#exceptions-and-return-codes)
3030

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
---
2+
title: Azure Blob storage input binding for Azure Functions
3+
description: Learn how to provide Azure Blob storage data to an Azure Function.
4+
author: craigshoemaker
5+
ms.topic: reference
6+
ms.date: 02/13/2020
7+
ms.author: cshoe
8+
---
9+
10+
# Azure Blob storage input binding for Azure Functions
11+
12+
The input binding allows you to read blob storage data as input to an Azure Function.
13+
14+
For information on setup and configuration details, see the [overview](./functions-bindings-storage-blob.md).
15+
16+
## Example
17+
18+
# [C#](#tab/csharp)
19+
20+
The following example is a [C# function](functions-dotnet-class-library.md) that uses a queue trigger and an input blob binding. The queue message contains the name of the blob, and the function logs the size of the blob.
21+
22+
```csharp
23+
[FunctionName("BlobInput")]
24+
public static void Run(
25+
[QueueTrigger("myqueue-items")] string myQueueItem,
26+
[Blob("samples-workitems/{queueTrigger}", FileAccess.Read)] Stream myBlob,
27+
ILogger log)
28+
{
29+
log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
30+
}
31+
```
32+
33+
# [C# Script](#tab/csharp-script)
34+
35+
<!--Same example for input and output. -->
36+
37+
The following example shows blob input and output bindings in a *function.json* file and [C# script (.csx)](functions-reference-csharp.md) code that uses the bindings. The function makes a copy of a text blob. The function is triggered by a queue message that contains the name of the blob to copy. The new blob is named *{originalblobname}-Copy*.
38+
39+
In the *function.json* file, the `queueTrigger` metadata property is used to specify the blob name in the `path` properties:
40+
41+
```json
42+
{
43+
"bindings": [
44+
{
45+
"queueName": "myqueue-items",
46+
"connection": "MyStorageConnectionAppSetting",
47+
"name": "myQueueItem",
48+
"type": "queueTrigger",
49+
"direction": "in"
50+
},
51+
{
52+
"name": "myInputBlob",
53+
"type": "blob",
54+
"path": "samples-workitems/{queueTrigger}",
55+
"connection": "MyStorageConnectionAppSetting",
56+
"direction": "in"
57+
},
58+
{
59+
"name": "myOutputBlob",
60+
"type": "blob",
61+
"path": "samples-workitems/{queueTrigger}-Copy",
62+
"connection": "MyStorageConnectionAppSetting",
63+
"direction": "out"
64+
}
65+
],
66+
"disabled": false
67+
}
68+
```
69+
70+
The [configuration](#configuration) section explains these properties.
71+
72+
Here's the C# script code:
73+
74+
```cs
75+
public static void Run(string myQueueItem, string myInputBlob, out string myOutputBlob, ILogger log)
76+
{
77+
log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
78+
myOutputBlob = myInputBlob;
79+
}
80+
```
81+
82+
# [JavaScript](#tab/javascript)
83+
84+
<!--Same example for input and output. -->
85+
86+
The following example shows blob input and output bindings in a *function.json* file and [JavaScript code](functions-reference-node.md) that uses the bindings. The function makes a copy of a blob. The function is triggered by a queue message that contains the name of the blob to copy. The new blob is named *{originalblobname}-Copy*.
87+
88+
In the *function.json* file, the `queueTrigger` metadata property is used to specify the blob name in the `path` properties:
89+
90+
```json
91+
{
92+
"bindings": [
93+
{
94+
"queueName": "myqueue-items",
95+
"connection": "MyStorageConnectionAppSetting",
96+
"name": "myQueueItem",
97+
"type": "queueTrigger",
98+
"direction": "in"
99+
},
100+
{
101+
"name": "myInputBlob",
102+
"type": "blob",
103+
"path": "samples-workitems/{queueTrigger}",
104+
"connection": "MyStorageConnectionAppSetting",
105+
"direction": "in"
106+
},
107+
{
108+
"name": "myOutputBlob",
109+
"type": "blob",
110+
"path": "samples-workitems/{queueTrigger}-Copy",
111+
"connection": "MyStorageConnectionAppSetting",
112+
"direction": "out"
113+
}
114+
],
115+
"disabled": false
116+
}
117+
```
118+
119+
The [configuration](#configuration) section explains these properties.
120+
121+
Here's the JavaScript code:
122+
123+
```javascript
124+
module.exports = function(context) {
125+
context.log('Node.js Queue trigger function processed', context.bindings.myQueueItem);
126+
context.bindings.myOutputBlob = context.bindings.myInputBlob;
127+
context.done();
128+
};
129+
```
130+
131+
# [Python](#tab/python)
132+
133+
<!--Same example for input and output. -->
134+
135+
The following example shows blob input and output bindings in a *function.json* file and [Python code](functions-reference-python.md) that uses the bindings. The function makes a copy of a blob. The function is triggered by a queue message that contains the name of the blob to copy. The new blob is named *{originalblobname}-Copy*.
136+
137+
In the *function.json* file, the `queueTrigger` metadata property is used to specify the blob name in the `path` properties:
138+
139+
```json
140+
{
141+
"bindings": [
142+
{
143+
"queueName": "myqueue-items",
144+
"connection": "MyStorageConnectionAppSetting",
145+
"name": "queuemsg",
146+
"type": "queueTrigger",
147+
"direction": "in"
148+
},
149+
{
150+
"name": "inputblob",
151+
"type": "blob",
152+
"path": "samples-workitems/{queueTrigger}",
153+
"connection": "MyStorageConnectionAppSetting",
154+
"direction": "in"
155+
},
156+
{
157+
"name": "$return",
158+
"type": "blob",
159+
"path": "samples-workitems/{queueTrigger}-Copy",
160+
"connection": "MyStorageConnectionAppSetting",
161+
"direction": "out"
162+
}
163+
],
164+
"disabled": false,
165+
"scriptFile": "__init__.py"
166+
}
167+
```
168+
169+
The [configuration](#configuration) section explains these properties.
170+
171+
Here's the Python code:
172+
173+
```python
174+
import logging
175+
import azure.functions as func
176+
177+
178+
def main(queuemsg: func.QueueMessage, inputblob: func.InputStream) -> func.InputStream:
179+
logging.info('Python Queue trigger function processed %s', inputblob.name)
180+
return inputblob
181+
```
182+
183+
# [Java](#tab/java)
184+
185+
This section contains the following examples:
186+
187+
* [HTTP trigger, look up blob name from query string](#http-trigger-look-up-blob-name-from-query-string)
188+
* [Queue trigger, receive blob name from queue message](#queue-trigger-receive-blob-name-from-queue-message)
189+
190+
#### HTTP trigger, look up blob name from query string
191+
192+
The following example shows a Java function that uses the `HttpTrigger` annotation to receive a parameter containing the name of a file in a blob storage container. The `BlobInput` annotation then reads the file and passes its contents to the function as a `byte[]`.
193+
194+
```java
195+
@FunctionName("getBlobSizeHttp")
196+
@StorageAccount("Storage_Account_Connection_String")
197+
public HttpResponseMessage blobSize(
198+
@HttpTrigger(name = "req",
199+
methods = {HttpMethod.GET},
200+
authLevel = AuthorizationLevel.ANONYMOUS)
201+
HttpRequestMessage<Optional<String>> request,
202+
@BlobInput(
203+
name = "file",
204+
dataType = "binary",
205+
path = "samples-workitems/{Query.file}")
206+
byte[] content,
207+
final ExecutionContext context) {
208+
// build HTTP response with size of requested blob
209+
return request.createResponseBuilder(HttpStatus.OK)
210+
.body("The size of \"" + request.getQueryParameters().get("file") + "\" is: " + content.length + " bytes")
211+
.build();
212+
}
213+
```
214+
215+
#### Queue trigger, receive blob name from queue message
216+
217+
The following example shows a Java function that uses the `QueueTrigger` annotation to receive a message containing the name of a file in a blob storage container. The `BlobInput` annotation then reads the file and passes its contents to the function as a `byte[]`.
218+
219+
```java
220+
@FunctionName("getBlobSize")
221+
@StorageAccount("Storage_Account_Connection_String")
222+
public void blobSize(
223+
@QueueTrigger(
224+
name = "filename",
225+
queueName = "myqueue-items-sample")
226+
String filename,
227+
@BlobInput(
228+
name = "file",
229+
dataType = "binary",
230+
path = "samples-workitems/{queueTrigger}")
231+
byte[] content,
232+
final ExecutionContext context) {
233+
context.getLogger().info("The size of \"" + filename + "\" is: " + content.length + " bytes");
234+
}
235+
```
236+
237+
In the [Java functions runtime library](/java/api/overview/azure/functions/runtime), use the `@BlobInput` annotation on parameters whose value would come from a blob. This annotation can be used with native Java types, POJOs, or nullable values using `Optional<T>`.
238+
239+
---
240+
241+
## Attributes and annotations
242+
243+
# [C#](#tab/csharp)
244+
245+
In [C# class libraries](functions-dotnet-class-library.md), use the [BlobAttribute](https://github.com/Azure/azure-webjobs-sdk/blob/dev/src/Microsoft.Azure.WebJobs.Extensions.Storage/Blobs/BlobAttribute.cs).
246+
247+
The attribute's constructor takes the path to the blob and a `FileAccess` parameter indicating read or write, as shown in the following example:
248+
249+
```csharp
250+
[FunctionName("BlobInput")]
251+
public static void Run(
252+
[QueueTrigger("myqueue-items")] string myQueueItem,
253+
[Blob("samples-workitems/{queueTrigger}", FileAccess.Read)] Stream myBlob,
254+
ILogger log)
255+
{
256+
log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
257+
}
258+
259+
```
260+
261+
You can set the `Connection` property to specify the storage account to use, as shown in the following example:
262+
263+
```csharp
264+
[FunctionName("BlobInput")]
265+
public static void Run(
266+
[QueueTrigger("myqueue-items")] string myQueueItem,
267+
[Blob("samples-workitems/{queueTrigger}", FileAccess.Read, Connection = "StorageConnectionAppSetting")] Stream myBlob,
268+
ILogger log)
269+
{
270+
log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
271+
}
272+
```
273+
274+
You can use the `StorageAccount` attribute to specify the storage account at class, method, or parameter level. For more information, see [Trigger - attributes and annotations](./functions-bindings-storage-blob-trigger.md#attributes-and-annotations).
275+
276+
# [C# Script](#tab/csharp-script)
277+
278+
Attributes are not supported by C# Script.
279+
280+
# [JavaScript](#tab/javascript)
281+
282+
Attributes are not supported by JavaScript.
283+
284+
# [Python](#tab/python)
285+
286+
Attributes are not supported by Python.
287+
288+
# [Java](#tab/java)
289+
290+
The `@BlobInput` attribute gives you access to the blob that triggered the function. If you use a byte array with the attribute, set `dataType` to `binary`. Refer to the [input example](#example) for details.
291+
292+
---
293+
294+
## Configuration
295+
296+
The following table explains the binding configuration properties that you set in the *function.json* file and the `Blob` attribute.
297+
298+
|function.json property | Attribute property |Description|
299+
|---------|---------|----------------------|
300+
|**type** | n/a | Must be set to `blob`. |
301+
|**direction** | n/a | Must be set to `in`. Exceptions are noted in the [usage](#usage) section. |
302+
|**name** | n/a | The name of the variable that represents the blob in function code.|
303+
|**path** |**BlobPath** | The path to the blob. |
304+
|**connection** |**Connection**| The name of an app setting that contains the [Storage connection string](../storage/common/storage-configure-connection-string.md) to use for this binding. If the app setting name begins with "AzureWebJobs", you can specify only the remainder of the name here. For example, if you set `connection` to "MyStorage", the Functions runtime looks for an app setting that is named "AzureWebJobsMyStorage". If you leave `connection` empty, the Functions runtime uses the default Storage connection string in the app setting that is named `AzureWebJobsStorage`.<br><br>The connection string must be for a general-purpose storage account, not a [blob-only storage account](../storage/common/storage-account-overview.md#types-of-storage-accounts).|
305+
|n/a | **Access** | Indicates whether you will be reading or writing. |
306+
307+
[!INCLUDE [app settings to local.settings.json](../../includes/functions-app-settings-local.md)]
308+
309+
## Usage
310+
311+
# [C#](#tab/csharp)
312+
313+
[!INCLUDE [functions-bindings-blob-storage-input-usage.md](../../includes/functions-bindings-blob-storage-input-usage.md)]
314+
315+
# [C# Script](#tab/csharp-script)
316+
317+
[!INCLUDE [functions-bindings-blob-storage-input-usage.md](../../includes/functions-bindings-blob-storage-input-usage.md)]
318+
319+
# [JavaScript](#tab/javascript)
320+
321+
Access blob data using `context.bindings.<NAME>` where `<NAME>` matches the value defined in *function.json*.
322+
323+
# [Python](#tab/python)
324+
325+
Access blob data via the parameter typed as [InputStream](https://docs.microsoft.com/python/api/azure-functions/azure.functions.inputstream?view=azure-python). Refer to the [input example](#example) for details.
326+
327+
# [Java](#tab/java)
328+
329+
The `@BlobInput` attribute gives you access to the blob that triggered the function. If you use a byte array with the attribute, set `dataType` to `binary`. Refer to the [input example](#example) for details.
330+
331+
---
332+
333+
## Next steps
334+
335+
- [Run a function when blob storage data changes](./functions-bindings-storage-blob-trigger.md)
336+
- [Write blob storage data from a function](./functions-bindings-storage-blob-output.md)

0 commit comments

Comments
 (0)