Node.js
AzureFunctions

Azure Functions の Node の Blob bindings でファイル名を指定する

More than 1 year has passed since last update.

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 では、パラメータは、contextinput しか不可の様子。

どないするねん、、、

解決策

結論としては、下記の{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が対応している。

Screen Shot 2017-10-07 at 4.53.10 PM.png

できました。めでたしめでたし

Screen Shot 2017-10-07 at 4.54.05 PM.png