JavaScript チュートリアル: Azure Functions と Blob Storage を使用してファイルをアップロードして分析する

このチュートリアルでは、画像を Azure Blob Storage にアップロードし、それを Azure Functions、Computer Vision、Cosmos DB を使用して処理する方法について学習します。 また、このプロセスの一環として Azure 関数のトリガーとバインドを実装する方法についても学習します。 これらのサービスを一緒に使用して、テキストを含むアップロードされた画像を分析し、テキストを抽出してから、その後の分析などの目的のためにデータベース行にテキストを格納します。

Azure Blob Storage は、クラウド用の Microsoft の非常にスケーラブルなオブジェクト ストレージ ソリューションです。 Blob Storage は、画像とドキュメントの格納、メディア ファイルのストリーミング、バックアップおよびアーカイブ データの管理などのために設計されています。 Blob Storage の詳細については、概要ページを参照してください。

警告

このチュートリアルでは、パブリックにアクセスできるストレージを使用して、このチュートリアルを完了するプロセスを簡略化しています。 匿名パブリック アクセスにはセキュリティ上のリスクがあります。 このリスクを修復する方法を確認してください。

Azure Cosmos DB は、最新のアプリ開発に対応するフル マネージドの NoSQL とリレーショナル データベースです。

Azure Functions は、非常にスケーラブルでサーバーレスなイベントドリブン関数として、小さなコード ブロックを記述して実行できるサーバーレス コンピューター ソリューションです。 Azure Functions の詳細については、概要ページを参照してください。

このチュートリアルで学習する内容は次のとおりです。

  • Blob Storage に画像とファイルをアップロードする
  • Azure 関数イベント トリガーを使用して、Blob Storage にアップロードされたデータを処理する
  • Azure AI サービスを使用して画像を分析する
  • Azure 関数の出力バインドを使用して Cosmos DB にデータを書き込む

画像 BLOB が Blob Storage に追加され、Azure 関数により分析され、分析内容が Cosmos DB に挿入されることを示すアーキテクチャ図。

前提条件

ストレージ アカウントとコンテナーを作成する

最初の手順では、アップロードされた BLOB データを保持するストレージ アカウントを作成します。このシナリオでは、テキストを含む画像になります。 ストレージ アカウントにはいくつかの異なるサービスが用意されていますが、このチュートリアルでは Blob Storage のみを利用します。

  1. Visual Studio Code で、Ctrl + Shift + P を選択して、コマンド パレットを開きます。

  2. [Azure Storage: ストレージ アカウントの作成 (詳細)] を探します。

  3. 次の表を使用して、ストレージ リソースを作成します。

    設定
    名前 msdocsstoragefunction または似たものを入力します。
    リソース グループ 先ほど作成した msdocs-storage-function リソース グループを作成します。
    静的 Web ホスティング 正解ではありません。
  4. Visual Studio Code で、Shift + Alt + A キーを押して、Azure Explorer を開きます。

  5. [Storage](ストレージ) セクションを展開し、サブスクリプション ノードを展開し、リソースが作成されるまで待ちます。

Visual Studio Code でコンテナーを作成する

  1. 引き続き Azure Explorer で、新しいストレージ リソースが見つかった状態で、リソースを展開してノードを表示します。
  2. [BLOB コンテナー] を右クリックし、[BLOB コンテナーの作成] を選択します。
  3. 名前 images を入力します。 これにより、プライベート コンテナーが作成されます。

Azure portal でプライベート コンテナーからパブリック コンテナーに変更する

この手順では、パブリック コンテナーが必要です。 その構成を変更するには、Azure portal で変更を行います。

  1. Azure Explorer でストレージ リソースを右クリックし、[ポータルで開く] を選択します。
  2. [データ ストレージ] セクションで、[コンテナー] を選択します。
  3. コンテナー images を見つけて、行の末尾にある ... (省略記号) を選択します。
  4. [アクセス レベルの変更] を選択します。
  5. [BLOB (BLOB 専用の匿名読み取りアクセスのみ)] を選択してから [OK] を選択します。
  6. Visual Studio Code に戻ります。

Visual Studio Code 内の接続文字列を取得する

  1. Visual Studio Code で、Shift + Alt + A キーを押して、Azure Explorer を開きます。
  2. ストレージ リソースを右クリックし、[接続文字列のコピー] を選択します。
  3. 後で使用するために、これを別の場所に貼り付けます。
  4. さらに、後で使用するために、ストレージ アカウント名 msdocsstoragefunction を書き留めておきます。

Azure AI Vision サービスを作成する

次に、アップロードしたファイルを処理する Azure AI Vision サービス アカウントを作成します。 Vision は Azure AI サービスの一部であり、画像からデータを抽出するためのさまざまな機能を提供します。 Azure AI Vision の詳細については、概要ページを参照してください。

  1. ポータルの上部にある検索バーで、Computer を検索し、Computer Vision というラベルの付いた結果を選択します。

  2. [Computer Vision] ページで、[+ 作成] を選択します。

  3. [Computer Vision の作成] ページで、次の値を入力します。

    • サブスクリプション: 目的のサブスクリプションを選びます。
    • リソース グループ: 前に作成した msdocs-storage-function リソース グループを使用します。
    • リージョン: 最も近いリージョンを選択します。
    • 名前: msdocscomputervision の名前を入力します。
    • 価格レベル: 利用可能な場合は [Free] を選び、それ以外の場合は [Standard S1] を選択します。
    • 条件に同意する場合は、[責任ある AI 通知] ボックスをオンにします

    新しい Computer Vision サービスを作成する方法を示すスクリーンショット。

  4. 下部にある [確認と作成] を選択します。 入力した情報が Azure によって検証されるのにしばらく時間がかかります。 設定が検証されてから、[作成] を選択すると、Azure によって Computer Vision サービスのプロビジョニングが開始されます。これにはしばらく時間がかかる場合があります。

  5. 操作が完了したら、[リソースに移動] を選択します。

Computer Vision のキーを取得する

次に、Azure 関数アプリで使用する Computer Vision サービスのシークレット キーとエンドポイント URL を見つける必要があります。

  1. [Computer Vision] の概要ページで、[キーとエンドポイント] を選択します。

  2. [キーとエンドポイント] ページで、[キー 1] の値と [エンドポイント] の値をコピーし、後で使用するためにどこかに貼り付けます。 エンドポイントは https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com/ という形式にする必要があります

Computer Vision サービスのキーと URL エンドポイントを取得する方法を示すスクリーンショット。

Cosmos DB サービス アカウントを作成する

ファイルの分析を格納するための Cosmos DB サービス アカウントを作成します。 Azure Cosmos DB は、最新のアプリ開発に対応するフル マネージドの NoSQL とリレーショナル データベースです。 Cosmos DB といくつかの異なる業界データベース用のサポート API について詳細を確認することができます。

このチュートリアルでは、リソースの作成時に API を指定しますが、Cosmos DB 用の Azure 関数バインドは、すべての Cosmos DB API に対して同じ方法で構成されます。

  1. ポータルの上部にある検索バーで、Azure Cosmos DB を検索し、結果を選択します。

  2. [Azure Cosmos DB] ページで、[+ 作成] を選択します。 API の選択肢のリストから [Azure Cosmos DB for NoSQL] を選択します。

  3. [Cosmos DB の作成] ページで、次の値を入力します。

    • サブスクリプション: 目的のサブスクリプションを選びます。
    • リソース グループ: 前に作成した msdocs-storage-function リソース グループを使用します。
    • [リージョン] :ご自分のリソース グループと同じリージョンを選択します。
    • 名前: msdocscosmosdb の名前を入力します。
    • 価格レベル: 利用可能な場合は [Free] を選び、それ以外の場合は [Standard S1] を選択します。
  4. 下部にある [確認と作成] を選択します。 入力した情報が Azure によって検証されるまでしばらく時間がかかります。 設定が検証されてから、[作成] を選択すると、Azure によって Computer Vision サービスのプロビジョニングが開始されます。これにはしばらく時間がかかる場合があります。

  5. 操作が完了したら、[リソースに移動] を選択します。

  6. [データ エクスプローラー] を選択し、[新しいコンテナー] を選択します。

  7. 次の設定を使用して新しいデータベースとコンテナーを作成します。

    • 新しいデータベース IDStorageTutorial を作成します。
    • 新しいコンテナー IDanalysis を入力します。
    • パーティション キー/type を入力します。
  8. 残りの既定の設定をそのままにして [OK] を選択します。

Cosmos DB の接続文字列を取得する

Azure 関数アプリで使用する Cosmos DB サービス アカウントの接続文字列を取得します。

  1. Cosmos DB の概要ページで、[キー] を選択します。

  2. [キー] ページで、後で使用するためにプライマリ接続文字列をコピーします。

サンプル プロジェクトをダウンロードして構成する

このチュートリアルで使用する Azure 関数のコードは、この GitHub リポジトリJavaScript-v4 サブディレクトリにあります。 以下のコマンドを使用してプロジェクトをクローンすることもできます。

git clone https://github.com/Azure-Samples/msdocs-storage-bind-function-service.git \
cd msdocs-storage-bind-function-service/javascript-v4 \
code .

サンプル プロジェクトでは次のタスクを実行します。

  • ストレージ アカウント、Computer Vision、Cosmos DB サービスに接続するための環境変数を取得する
  • アップロードされたファイルを BLOB パラメーターとして受け入れる
  • Computer Vision サービスを使用して BLOB を分析する
  • 出力バインディングを使用して、分析された画像テキストを JSON オブジェクトとして Cosmos DB に挿入する

プロジェクトをダウンロードして開いたら、理解する必要がある重要な概念がいくつかあります。

概念 目的
機能 Azure 関数は、関数コードとバインドの両方によって定義されます。 これらは ./src/functions/process-blobs.js にあります。
トリガーとバインド トリガーとバインドでは、関数との間でのやり取りが予想されるデータと、そのデータを送信または受信するサービスを示します。

このチュートリアルで使用されるトリガーとバインドは、サービスに接続するコードを記述する必要をなくすことで開発プロセスを迅速化します。

入力ストレージ BLOB トリガー

このコードは、BLOB が images コンテナーにアップロードされるときに関数がトリガーされることを指定します。 関数は、階層フォルダーを含む任意の BLOB 名でトリガーされます。


// ...preceding code removed for brevity

app.storageBlob('process-blob-image', { 
    path: 'images/{name}',                // Storage container name: images, Blob name: {name}
    connection: 'StorageConnection',      // Storage account connection string
    handler: async (blob, context) => {

// ... function code removed for brevity
  • app.storageBlob - ストレージ BLOB 入力トリガーは、Blob Storage のアップロード イベントに関数をバインドするために使用されます。 トリガーには、次の 2 つの必須パラメーターがあります。
    • path: トリガーがイベントを監視するパス。 パスには、コンテナー名 images と、BLOB 名の変数の置換が含まれます。 この BLOB 名は、name プロパティから取得されます。
    • {name}: アップロードされた BLOB の名前。 blob の使用は、関数に入る BLOB のパラメーター名です。 値 blob を変更しないでください。
    • connection: ストレージ アカウントの接続文字列。 値 StorageConnection は、ローカルで開発するときは local.settings.json ファイル内の名前と一致します。

出力 Cosmos DB トリガー

関数が終了すると、関数は返されたオブジェクトを Cosmos DB に挿入するデータとして使用します。


// ... function definition ojbect
app.storageBlob('process-blob-image', { 
    
        // removed for brevity    
        
        // Data to insert into Cosmos DB
        const id = uuidv4().toString();
        const analysis = await analyzeImage(blobUrl);
        
        // `type` is the partition key 
        const dataToInsertToDatabase = {
                id,
                type: 'image',
                blobUrl,
                blobSize: blob.length,
                analysis,
                trigger: context.triggerMetadata
            }

        return dataToInsertToDatabase;
    }),

    // Output binding for Cosmos DB
    return: output.cosmosDB({
        connection: 'CosmosDBConnection',
        databaseName:'StorageTutorial',
        containerName:'analysis'
    })
});

この記事のコンテナーでは、必須プロパティは次のとおりです。

  • id: Cosmos DB が新しい行を作成するために必要な ID。

  • /type: コンテナーが作成されたときに指定されたパーティション キー。

  • output.cosmosDB - Cosmos DB 出力トリガーは、関数の結果を Cosmos DB に挿入するために使用されます。

    • connection: ストレージ アカウントの接続文字列。 値 StorageConnectionlocal.settings.json ファイル内の名前と一致します。
    • databaseName: 接続する Cosmos DB データベース。
    • containerName: 関数によって返される解析された画像テキスト値を書き込むためのテーブルの名前。 テーブルは既に存在している必要があります。

Azure 関数コード

完全な関数コードを次に示します。

const { app, input, output } = require('@azure/functions');
const { v4: uuidv4 } = require('uuid');
const { ApiKeyCredentials } = require('@azure/ms-rest-js');
const { ComputerVisionClient } = require('@azure/cognitiveservices-computervision');
const sleep = require('util').promisify(setTimeout);

const STATUS_SUCCEEDED = "succeeded";
const STATUS_FAILED = "failed"

const imageExtensions = ["jpg", "jpeg", "png", "bmp", "gif", "tiff"];

async function analyzeImage(url) {

    try {

        const computerVision_ResourceKey = process.env.ComputerVisionKey;
        const computerVision_Endpoint = process.env.ComputerVisionEndPoint;

        const computerVisionClient = new ComputerVisionClient(
            new ApiKeyCredentials({ inHeader: { 'Ocp-Apim-Subscription-Key': computerVision_ResourceKey } }), computerVision_Endpoint);

        const contents = await computerVisionClient.analyzeImage(url, {
            visualFeatures: ['ImageType', 'Categories', 'Tags', 'Description', 'Objects', 'Adult', 'Faces']
        });

        return contents;

    } catch (err) {
        console.log(err);
    }
}
app.storageBlob('process-blob-image', { 
    path: 'images/{name}',
    connection: 'StorageConnection',
    handler: async (blob, context) => {

        context.log(`Storage blob 'process-blob-image' url:${context.triggerMetadata.uri}, size:${blob.length} bytes`);

        const blobUrl = context.triggerMetadata.uri;
        const extension = blobUrl.split('.').pop();

        if(!blobUrl) {
            // url is empty
            return;
        } else if (!extension || !imageExtensions.includes(extension.toLowerCase())){
            // not processing file because it isn't a valid and accepted image extension
            return;
        } else {
            //url is image
            const id = uuidv4().toString();
            const analysis = await analyzeImage(blobUrl);
            
            // `type` is the partition key 
            const dataToInsertToDatabase = {
                    id,
                    type: 'image',
                    blobUrl,
                    blobSize: blob.length,
                    ...analysis,
                    trigger: context.triggerMetadata
                }

            return dataToInsertToDatabase;
        }

        
    },
    return: output.cosmosDB({
        connection: 'CosmosDBConnection',
        databaseName:'StorageTutorial',
        containerName:'analysis'
    })
});

このコードでは、Blob Storage の接続文字列や Computer Vision キーなど、環境変数から重要な構成値も取得します。 これらの環境変数は、デプロイ後に Azure 関数環境に追加されます。

既定の関数では、AnalyzeImage という 2 つ目のメソッドも利用されます。 このコードでは、Computer Vision アカウントの URL エンドポイントとキーを使用して、画像を処理するように Computer Vision に要求します。 要求によって、イメージ内で検出されたすべてのテキストが返されます。 このテキストは、送信バインディングを使用して Cosmos DB に書き込まれます。

ローカル設定を構成する

プロジェクトをローカルで実行するには、./local.settings.json ファイルに環境変数を入力します。 Azure リソースの作成時に前に保存した値をプレースホルダー値に入力します。

Azure 関数コードはローカルで実行されますが、ローカル エミュレーターを使用するのではなく、Storage 用のクラウドベースのサービスに接続されます。

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "AzureWebJobsStorage": "",
    "StorageConnection": "STORAGE-CONNECTION-STRING",
    "StorageAccountName": "STORAGE-ACCOUNT-NAME",
    "StorageContainerName": "STORAGE-CONTAINER-NAME",
    "ComputerVisionKey": "COMPUTER-VISION-KEY",
    "ComputerVisionEndPoint":  "COMPUTER-VISION-ENDPOINT",
    "CosmosDBConnection": "COSMOS-DB-CONNECTION-STRING"
  }
}

Azure Functions アプリを作成する

これで、Visual Studio Code 拡張機能を使用してアプリケーションを Azure にデプロイする準備ができました。

  1. Visual Studio Code で、Shift + Alt + A キーを押して、Azure エクスプローラーを開きます。

  2. [Functions] セクションで、サブスクリプションを見つけて右クリックし、[Create Function App in Azure (Advanced)](Azure での関数アプリの作成 (詳細)) を選択します。

  3. 次のテーブルを使用して、Function リソースを作成します。

    設定
    名前 msdocsprocessimage などと入力します。
    ランタイム スタック Node.js LTS バージョンを選択します。
    プログラミング モデル [v4] を選択します。
    OS [Linux] を選択します。
    リソース グループ 先ほど作成した msdocs-storage-function リソース グループを選択します。
    場所 ご自分のリソース グループと同じリージョンを選択します。
    プランの種類 [従量課金プラン] を選択します。
    Azure ストレージ 以前に作成したストレージ アカウントを選択します。
    Application Insights 今はスキップします。
  4. Azure により、要求されたリソースのプロビジョニングが開始されます。完了するまで少し時間がかかります。

Azure Functions アプリのデプロイ

  1. 前のリソース作成プロセスが完了したら、Azure エクスプローラーの [Functions] セクションで新しいリソースを右クリックし、[Deploy to Function App](関数アプリにデプロイする) を選択します。
  2. [...を展開しますか] というメッセージが表示されたら、[Deploy](デプロイ) を選択します。
  3. プロセスが完了すると、通知が表示され、[アップロード設定] を含む選択肢が表示されます。 そのオプションを選択します。 これにより、local.settings.json ファイルの値が Azure 関数アプリにコピーされます。 通知を選択する前に通知が消えた場合は、次のセクションに進みます。

Storage と Computer Vision のためのアプリ設定を追加する

通知で [Upload settings](設定のアップロード) を選択した場合は、このセクションをスキップします。

Azure 関数は正常にデプロイされましたが、Storage アカウントと Computer Vision サービスにまだ接続できません。 まず、正しいキーと接続文字列を Azure Functions アプリの構成設定に追加する必要があります。

  1. Azure エクスプローラーの [Functions] セクションでリソースを探し、[アプリケーション設定] を右クリックし、[新しい設定の追加] を選択します。

  2. 次のシークレットの新しいアプリ設定を入力します。 ローカル プロジェクトのシークレット値をコピーして、local.settings.json ファイルに貼り付けます。

    設定
    StorageConnection
    StorageAccountName
    StorageContainerName
    ComputerVisionKey
    ComputerVisionEndPoint
    CosmosDBConnection

これで、Azure 関数をさまざまなサービスに接続するために必要なすべての環境変数を準備できました。

画像を Blob Storage にアップロードする

これで、アプリケーションをテストする準備ができました。 BLOB をコンテナーにアップロードしてから、画像内のテキストが Cosmos DB に保存されたことを確認できます。

  1. Visual Studio Code の Azure エクスプローラーで、[Storage] セクションから Storage リソースを見つけて展開します。
  2. [BLOB コンテナー] を展開し、コンテナー名 images を右クリックし、[ファイルのアップロード] を選択します。
  3. ダウンロード可能なサンプル プロジェクトのルートにある images フォルダーに含まれるいくつかのサンプル画像を見つけることができます。独自のものを使用することもできます。
  4. [Destination directory](宛先ディレクトリ) については、既定値 / をそのまま使用します。
  5. ファイルがアップロードされ、コンテナーに一覧表示されるまで待ちます。

画像のテキスト分析を表示する

次に、アップロードによって Azure 関数がトリガーされたこと、および画像内のテキストが分析されて Cosmos DB に正しく保存されたことを確認できます。

  1. Visual Studio Code の Azure エクスプローラーの [Azure Cosmos DB] ノードで、お使いのリソースを選択し、それを展開してデータベース StorageTutorial を見つけます。

  2. データベース ノードを展開します。

  3. analysis コンテナーが利用できるようになっています。 コンテナーの [ドキュメント] ノードを選択して、内部のデータをプレビューします。 アップロードされたファイルの処理済み画像テキストのエントリが表示されるはずです。

    {
        "id": "3cf7d6f0-a362-421e-9482-3020d7d1e689",
        "type": "image",
        "blobUrl": "https://msdocsstoragefunction.blob.core.windows.net/images/presentation.png",
        "blobSize": 1383614,
        "analysis": {  ... details removed for brevity ...
            "categories": [],
            "adult": {},
            "imageType": {},
            "tags": [],
            "description": {},
            "faces": [],
            "objects": [],
            "requestId": "eead3d60-9905-499c-99c5-23d084d9cac2",
            "metadata": {},
            "modelVersion": "2021-05-01"
        },
        "trigger": { 
            "blobTrigger": "images/presentation.png",
            "uri": "https://msdocsstorageaccount.blob.core.windows.net/images/presentation.png",
            "properties": {
                "lastModified": "2023-07-07T15:32:38+00:00",
                "createdOn": "2023-07-07T15:32:38+00:00",
                "metadata": {},
                ... removed for brevity ...
                "contentLength": 1383614,
                "contentType": "image/png",
                "accessTier": "Hot",
                "accessTierInferred": true,
            },
            "metadata": {},
            "name": "presentation.png"
        },
        "_rid": "YN1FAKcZojEFAAAAAAAAAA==",
        "_self": "dbs/YN1FAA==/colls/YN1FAKcZojE=/docs/YN1FAKcZojEFAAAAAAAAAA==/",
        "_etag": "\"7d00f2d3-0000-0700-0000-64a830210000\"",
        "_attachments": "attachments/",
        "_ts": 1688743969
    }
    

お疲れさまでした。 Azure Functions と Computer Vision を使用して Blob Storage にアップロードされた画像の処理に成功しました。

トラブルシューティング

この手順での問題のトラブルシューティングに役立つ次の表を使用してください。

問題 解像度
Only absolute URLs are supported による await computerVisionClient.read(url); エラー ComputerVisionEndPoint エンドポイントが https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com/ の形式であることを確認します。

リソースをクリーンアップする

このアプリケーションを引き続き使用しない場合は、リソース グループを削除して作成したリソースを削除することができます。

  1. Azure エクスプローラーから [リソース グループ] を選択します。
  2. 一覧から msdocs-storage-function リソース グループを見つけて右クリックします。
  3. [削除] を選択します。 リソース グループを削除するプロセスが完了するまでに数分かかる場合があります。

サンプル コード

次のステップ