I have an Azure Function with Timer Trigger, and then I want to generate a file with dynamic (defined in runtime) name and contents and save it to e.g. OneDrive.
My func
To have full control over the name and path of an output during function execution, you need to use imperative binding
For example: function.json
{
"type": "blob",
"name": "outputBinder",
"path": "export/test",
"connection": "AzureWebJobsStorage",
"direction": "out"
},
Function:
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log, IBinder outputBinder)
{
var attribute new BlobAttribute($"{some dynamic path}/{some dynamic filename}", FileAccess.Write);
using (var stream = await outputBinder.BindAsync<Stream>(attribute))
{
// do whatever you want with this stream here...
}
}
Here is how you could do it:
#r "Microsoft.Azure.WebJobs.Extensions.ApiHub"
using System;
using System.IO;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host.Bindings.Runtime;
public static async Task Run(TimerInfo myTimer, TraceWriter log, Binder binder)
{
log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
var fileName = "mypath/" + DateTime.Now.ToString("yyyy-MM-ddThh-mm-ss") + ".txt";
var attributes = new Attribute[]
{
new ApiHubFileAttribute("onedrive_ONEDRIVE", fileName, FileAccess.Write)
};
var writer = await binder.BindAsync<TextWriter>(attributes);
var content = $"Generated at {DateTime.Now} by Azure Functions";
writer.Write(content);
}
And the function.json
file:
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "10 * * * * *"
},
{
"type": "apiHubFile",
"name": "outputFile",
"connection": "onedrive_ONEDRIVE",
"direction": "out"
}
],
"disabled": false
}
You shouldn't really need the apiHubFile
declaration in your function.json
but because of a bug I noticed today it should still be there. we will fix that bug.