共用方式為


JavaScript 教學課程:使用 Azure Functions 和 Blob 儲存體來上傳和分析檔案

在本教學課程中,您將瞭解如何將影像上傳至 Azure Blob 儲存體,並使用 Azure Functions、電腦視覺 和 Cosmos DB 來處理它。 您也將了解如何在此程序中實作 Azure 函式觸發程序和繫結。 這些服務會一起分析包含文字的上傳影像、擷取其中的文字,然後將文字儲存在資料庫資料列中,以供稍後進行分析或其他用途。

Azure Blob 儲存體是 Microsoft 針對雲端所推出的可大幅調整物件儲存體解決方案。 Blob 儲存體專門設計來儲存影像和文件、串流媒體檔案、管理備份和封存資料等等。 您可以在概觀頁面上深入了解 Blob 儲存體。

警告

本教學課程旨在快速採用,因此不會遵循預設的安全需求。 若要深入瞭解此案例與默認目標,請移至 安全性考慮

Azure Cosmos DB 是適用於新式應用程式開發的完全受控 NoSQL 和關聯式資料庫。

Azure Functions 是無伺服器的電腦解決方案,可讓您將小型程式碼區塊撰寫為可高度調整、無伺服器、事件驅動的函式並加以執行。 您可以在概觀頁面上深入了解 Azure Functions。

在本教學課程中,您將了解如何:

  • 將影像和檔案上傳至 Blob 儲存體
  • 使用 Azure 函式事件觸發程序來處理上傳至 Blob 儲存體的資料
  • 使用 Azure AI 服務來分析影像
  • 使用 Azure 函式輸出繫結將資料寫入到 Cosmos DB

顯示影像 Blob 的架構圖表會新增至 Blob 記憶體,然後由 Azure 函式分析,並將分析插入 Cosmos DB 中。

必要條件

建立儲存體帳戶和容器

第一個步驟是建立儲存體帳戶來保存上傳的 Blob 資料,在此案例中為包含文字的影像。 儲存體帳戶會提供數個不同的服務,但本教學課程只使用 Blob 儲存體。

  1. 在 Visual Studio Code 中,選取 Ctrl + Shift + P,以開啟命令選擇區。

  2. 搜尋 Azure 儲存體:建立儲存體 帳戶 (進階)

  3. 使用下表來建立儲存體資源。

    設定
    名稱 輸入 msdocsstoragefunction 或類似的內容。
    資源群組 建立您先前建立的 msdocs-storage-function 資源群組。
    靜態 Web 裝載 否。
  4. 在 Visual Studio Code 中,選取 Shift + Alt + A 以開啟 Azure Explorer。

  5. 展開 [儲存體] 區段,展開您的訂用帳戶節點,並等候資源建立。

在 Visual Studio Code 中建立容器

  1. 仍在找到新儲存體資源的 Azure Explorer 中,展開資源以查看節點。
  2. 以滑鼠右鍵按一下 [Blob 容器],然後選取 [建立 Blob 容器]
  3. 輸入名稱 images。 這會建立私人容器。

從私人變更為 Azure 入口網站 中的公用容器

此程序需要有公用容器。 若要變更該組態,請在 Azure 入口網站中進行變更。

  1. 以滑鼠右鍵按一下 Azure Explorer 中的儲存體資源,然後選取 [在入口網站中開啟]
  2. 在 [資料儲存體] 區段中,選取 [容器]
  3. 尋找您的容器 images,然後選取行尾的 ... (省略符號)。
  4. 選取 [變更存取層級]
  5. 選取 [Blob (僅限 Blob 的匿名讀取權限)],然後選取 [確定]
  6. 返回 Visual Studio Code。

在 Visual Studio Code 中擷取連接字串

  1. 在 Visual Studio Code 中,選取 Shift + Alt + A 以開啟 Azure Explorer。
  2. 以滑鼠右鍵按一下您的儲存體資源,然後選取 [複製連接字串]
  3. 將此連接字串貼在某處以供稍後使用。
  4. 記下儲存體帳戶名稱 msdocsstoragefunction 以供稍後使用。

建立 Azure AI 視覺服務

接下來,建立 Azure AI 視覺服務帳戶,以處理上傳的檔案。 視覺是 Azure AI 服務的一部分,並提供各種功能以從影像中擷取出資料。 您可以在概觀頁面上深入了解 Azure AI 視覺。

  1. 在入口網站頂端的搜尋列中,搜尋電腦,然後選取標示為電腦視覺的結果。

  2. 在 [電腦視覺] 頁面上,選取 [+ 建立]

  3. 在 [建立電腦視覺] 頁面上,輸入下列值:

    • 訂用帳戶:選擇您想要的訂用帳戶。
    • 資源群組:使用您稍早建立的 msdocs-storage-function 資源群組。
    • 區域:選取與您最接近的區域。
    • 名稱:輸入 msdocscomputervision 的名稱。
    • 定價層:如果可用,請選擇 [免費],否則請選擇 [標準 S1]
    • 如果您同意條款,請核取 [負責任 AI 注意事項] 方塊

    顯示如何建立新 電腦視覺 服務的螢幕快照。

  4. 選取底部的 [檢閱 + 建立]。 Azure 會花一點時間驗證您輸入的資訊。 驗證過設定後,選擇 [建立],Azure 便會開始佈建電腦視覺服務,這可能需要一些時間。

  5. 作業完成時,請選取 [移至資源]

擷取電腦視覺金鑰

接下來,我們需要尋找電腦視覺服務的秘密金鑰和端點 URL 以便在 Azure 函式應用程式中使用。

  1. 在 [電腦視覺] 概觀頁面上,選取 [金鑰和端點]

  2. 在 [金鑰和端點] 頁面上,複製 [金鑰 1] 值和 [端點] 值,並將其貼到某處以供稍後使用。 端點的格式應為 https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com/

顯示如何擷取 電腦視覺 服務的金鑰和 URL 端點的螢幕快照。

建立 Cosmos DB 服務帳戶

建立 Cosmos DB 服務帳戶來儲存檔案的分析資料。 Azure Cosmos DB 是適用於新式應用程式開發的完全受控 NoSQL 和關聯式資料庫。 您可以深入了解 Cosmos DB 及其針對數個不同產業資料庫提供的 API 支援。

雖然本教學課程會在您建立資源時指定 API,但適用於 Cosmos DB 的 Azure Function 繫結在所有 Cosmos DB API 上的設定方式都相同。

  1. 在入口網站頂端的搜尋列中,搜尋 Azure Cosmos DB,然後選取該結果。

  2. 在 [Azure Cosmos DB] 頁面上,選取 [+ 建立]。 從 API 選項清單中選取 [Azure Cosmos DB for NoSQL]

  3. 在 [建立 Cosmos DB] 頁面上,輸入下列值:

    • 訂用帳戶:選擇您想要的訂用帳戶。
    • 資源群組:使用您稍早建立的 msdocs-storage-function 資源群組。
    • 區域:選取與您資源群組相同的區域。
    • 名稱:輸入 msdocscosmosdb 的名稱。
    • 定價層:如果可用,請選擇 [免費],否則請選擇 [標準 S1]
  4. 選取底部的 [檢閱 + 建立]。 Azure 會花一點時間驗證您輸入的資訊。 驗證過設定後,選擇 [建立],Azure 便會開始佈建電腦視覺服務,這可能需要一些時間。

  5. 作業完成時,請選取 [移至資源]

  6. 選取 [資料總管],然後選取 [新增容器]

  7. 使用下列設定建立新的資料庫和容器:

    • 建立新的資料庫識別碼StorageTutorial
    • 建立新的容器識別碼analysis
    • 輸入分割區索引鍵/type
  8. 保留其餘的預設設定,然後選取 [確定]

取得 Cosmos DB 連接字串

取得 Cosmos DB 服務帳戶的連接字串,以便在 Azure Function 應用程式中使用。

  1. 在 [Cosmos DB] 概觀頁面上,選取 [金鑰]

  2. 在 [金鑰] 頁面上,複製 [主要連接字串] 以供稍後使用。

下載並設定範例專案

您可以在此 GitHub 存放庫JavaScript-v4 子目錄中找到本教學課程中使用的 Azure Function 程式碼。 您也可以使用下列命令來複製專案。

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

範例專案會完成下列工作:

  • 擷取環境變數以連線到儲存體帳戶、電腦視覺和 Cosmos DB 服務
  • 接受上傳的檔案以作為 Blob 參數
  • 使用電腦視覺服務來分析 Blob
  • 使用輸出繫結,將分析的影像文字當成 JSON 物件插入 Cosmos DB

下載並開啟專案之後,有一些需要了解的基本概念:

概念 目的
函式 Azure Function 是由函式程式碼和繫結所定義。 這些程式碼和繫結位於 ./src/functions/process-blobs.js
觸發和繫結 觸發程序和繫結會指出預期要傳入或移出函式的資料,以及即將傳送或接收該資料的服務。

本教學課程中使用的觸發程序和繫結因為不再需要撰寫程式碼來連接服務,因此可以加速開發程序。

輸入儲存體 Blob 觸發程序

程式碼可指定 Blob 上傳至影像容器後觸發的函式。 此函式會在任何含有階層資料夾的 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 儲存體中的上傳事件。 觸發程序有兩個必要參數:
    • 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 建立新資料列所需的識別碼。

  • /type:用來建立容器的指定分割區索引鍵。

  • output.cosmosDB - Cosmos DB 輸出觸發程序用來將函式結果插入 Cosmos DB。

    • connection:儲存體帳戶的連接字串StorageConnection 值符合 local.settings.json 檔案中的名稱。
    • databaseName:要連接的 Cosmos DB 資料庫。
    • containerName:資料表的名稱,以寫入函式所傳回的剖析影像文字值。 此資料表必須已經存在。

Azure Function 程式碼

以下是完整的函式程式碼。

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 儲存體連接字串和電腦視覺金鑰。 這些環境變數會在 Azure 函式環境部署之後新增至其中。

預設函式也會使用名為 AnalyzeImage 的第二個方法。 此程式碼會使用電腦視覺帳戶的 URL 端點和金鑰,向電腦視覺提出處理影像的要求。 要求會傳回影像中探索到的所有文字。 此文字會使用輸出繫結寫入至 Cosmos DB。

配置本機設定

若要在本機執行專案,請在 ./local.settings.json 檔案中輸入環境變數。 以您稍早在建立 Azure 資源時所儲存的值來填入到預留位置值。

雖然 Azure Function 程式碼會在本機執行,但它會連線到儲存體的雲端式服務,而不會使用任何本機模擬器。

{
  "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 Explorer。

  2. 在 [函式] 區段中,尋找並以滑鼠右鍵按一下訂用帳戶,然後選取 [在 Azure 中建立函式應用程式 (進階)]

  3. 使用下表來建立 Function 資源。

    設定
    名稱 輸入 msdocsprocessimage 或類似的內容。
    執行階段堆疊 選取 Node.js LTS 版本。
    程式設計模型 選取 v4
    OS 選取 [Linux]
    資源群組 選擇您先前建立的 msdocs-storage-function 資源群組。
    地點 選取與您資源群組相同的區域。
    方案類型 選取 [使用量]
    Azure 儲存體 選取您稍早建立的儲存體帳戶。
    Application Insights 暫時跳過。
  4. Azure 會佈建所要求的資源,這需要一些時間才能完成。

部署 Azure Functions 應用程式

  1. 當先前的資源建立程序完成時,以滑鼠右鍵按一下 Azure Explorer 的 [函式] 區段中的新資源,然後選取 [部署至函式應用程式]
  2. 如果系統詢問「您是否確定要部署...」,請選取 [部署]
  3. 當程序完成時,通知隨即出現,其中包含 [上傳設定] 等選擇。 選取該選項。 這會將 local.settings.json 檔案中的值複製到您的 Azure Function 應用程式中。 如果通知在您可選取之前消失,請繼續進行下一節。

新增儲存體和電腦視覺的應用程式設定

如果您在通知中選取了 [上傳設定],請略過本節。

Azure 函式已成功完成部署,但還無法連線到我們的儲存體帳戶和電腦視覺服務。 您必須先將正確的金鑰和連接字串新增至 Azure Functions 應用程式的組態設定。

  1. 在 Azure Explorer 的 [函式] 區段中尋找您的資源,以滑鼠右鍵按一下 [應用程式設定],然後選取 [新增設定]

  2. 輸入下列秘密的新應用程式設定。 從您的本機專案複製秘密值並貼在 local.settings.json 檔案中。

    設定
    StorageConnection
    StorageAccountName
    StorageContainerName
    ComputerVisionKey
    ComputerVisionEndPoint
    CosmosDBConnection

要將 Azure 函式連線到不同服務所需的所有環境變數目前均已備妥。

將影像上傳至 Blob 儲存體

您現在已做好準備,可以開始測試我們的應用程式了! 您可以將 Blob 上傳至容器,然後確認影像中的文字已儲存至 Cosmos DB。

  1. 在 Visual Studio Code 的 Azure Explorer 中,於 [儲存體] 區段中尋找並展開您的儲存體資源。
  2. 展開 [Blob 容器]並以滑鼠右鍵按一下您的容器名稱 images,然後選取 [上傳檔案]
  3. 您可以在可下載範例專案的根目錄中,找到一些包含在 images 資料夾內的範例影像,或者您也可以使用自己的影像。
  4. 針對 [目的地目錄],接受預設值 /
  5. 等到檔案上傳並列在容器中。

檢視影像的文字分析

接下來,您可以確認上傳是否觸發了 Azure 函式,而且影像中的文字已正確分析並儲存至 Cosmos DB。

  1. 在 Visual Studio Code 中,使用 Azure Explorer,在 Azure Cosmos DB 節點下方選取您的資源後展開以尋找資料庫 StorageTutorial

  2. 展開資料庫節點。

  3. 分析容器現在應該可供使用。 選取容器的文件節點以預覽其中的資料。 您應會看到所上傳檔案的已處理影像文字項目。

    {
        "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 和電腦視覺處理上傳至 Blob 儲存體的影像。

疑難排解

使用下表來協助進行此程序期間的問題疑難排解。

問題 解決方案
包含 Only absolute URLs are supportedawait computerVisionClient.read(url); 錯誤 確定您的 ComputerVisionEndPoint 端點的格式為 https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com/

安全性考量

此解決方案作為初學者教學課程,不會示範預設的安全做法。 這是刻意可讓您成功部署解決方案。 成功部署后的下一個步驟是保護資源。 此解決方案會使用三個 Azure 服務,每個服務都有自己的安全性功能和預設設定的考慮:

範例指令碼

清除資源

如果您不打算繼續使用此應用程式,則可以移除資源群組來刪除所建立的資源。

  1. 從 Azure Explorer 選取 [資源群組]
  2. 從清單中尋找並以滑鼠右鍵按一下 msdocs-storage-function 資源群組。
  3. 選取 [刪除]。 刪除資源群組的流程可能需要幾分鐘的時間才能完成。