Azure Functions の node で Storage Account のBindings を使って、ファイル名を指定しながら、ファイルを書いてみたい。ところが、マニュアルによると、動的なバインディングは、C# のみらしい。
binding で名前指定ができるらしい。
ファイルアップロードするときに、ファイル名指定を当然したいだろう。どうやったら指定できるだろうか。ちなみに、私のケースでは、HttpTrigger でアップロードして、Storage Account の bindings に流すパターン。
これの定義を参照にしてみよう。
{
"bindings": [
{
"name": "myBlob",
"type": "blobTrigger",
"direction": "in",
"path": "images-original/{name}",
"connection": "thumbnailfunction_STORAGE",
"dataType": "binary"
},
{
"type": "blob",
"name": "$return",
"path": "images-thumbnail/{name}",
"connection": "thumbnailfunction_STORAGE",
"direction": "out"
}
],
"disabled": false
}
こんな感じで、{name}
を指定できたらええやん。ちなみにC# だと、このname を最初に呼ばれるメソッドのパラメータに追加できたりするが、node
だとそうは問屋が降ろさない。w パラメータを追加したら派手なエラーになった。
module.exports = function (context, req, name) {
こんな感じにすると派手なエラーが
An unhandled exception occurred while processing the request.
InvalidOperationException: No value for named parameter 'name'.
Microsoft.Azure.WebJobs.Host.Bindings.Path.BindingTemplateToken+ExpressionToken.Evaluate(IReadOnlyDictionary<string, object> bindingData)
FunctionInvocationException: Exception while executing function: Functions.BindingTest
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
マニュアルを見ると、node
では、パラメータは、context
と input
しか不可の様子。
どないするねん、、、
解決策
結論としては、下記の{filename}
や {extension}
はプログラムの中身から渡せない。orz 。しかし、インプットのバインディングから引き継ぐということなので、httpトリガーの URL から引き継ぐようにする。Route
を指定してあげると良い。ちなみに、function.json
は、ポータルだと、Function名 > Integrate > Advanced editor でみれる。
function.json
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"route": "BindingTest/{filename}/{extension}",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "blob",
"name": "outputBlob",
"path": "outcontainer2/{filename}.{extension}",
"connection": "carreviewstr_STORAGE",
"direction": "out"
}
],
"disabled": false
}
そんで、コードはこんな感じ。テンプレートにちょっと足しただけ。
module.exports = function (context, req) {
context.bindings.outputBlob = "hello!";
if (req.query.name || (req.body && req.body.name)) {
context.res = {
// status: 200, /* Defaults to 200 */
body: "Hello " + (req.query.name || req.body.name)
};
}
else {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
context.done();
};
テスト実行
を、勝手に、GUIが対応している。
できました。めでたしめでたし