Next.js の API と Playwright のコンテナを連動させる(後編)

公開日 :

このシリーズとしては最終回です。スクリーンショットを撮るところまでできたので、ストレージと連携させていきます。今回は、Azure Blob Storage と連携する形に仕上げていきます。

Azure Blob Storage 連携の下準備

今回は Azure Blob Storage に取得したサムネイルの画像を配置、その画像があればスクリーンショットの処理を実行しない、という実装をしていきます。今回はストレージの作成に関しては省略します。

まず、現在作成しているサンプルで Azure Blob Storage を利用できるように、@azure/storage-blob のモジュールをインストールします。

npm install -D @azure/storage-blob

続いて、前回のファイルに対して以下のコードを追加します。

import {
  BlobServiceClient,
  StorageSharedKeyCredential,
} from "@azure/storage-blob";

続いて、環境変数として値を保つために、ストレージアカウント、アクセスキーおよびコンテナの値を設定するために、.env ファイルには以下の項目を追加します。

AZURE_STORAGE_ACCOUNT=
AZURE_STORAGE_ACCESS_KEY=
AZURE_STORAGE_CONTAINER=

上記の値をプログラムで読み込むことができるように、以下のコードを追加しておきます。

  const AZURE_STORAGE_ACCOUNT = process.env["AZURE_STORAGE_ACCOUNT"]
|| "";
  const AZURE_STORAGE_ACCESS_KEY = process.env["AZURE_STORAGE_ACCESS_KEY"] 
|| "";
  const AZURE_STORAGE_CONTAINER = process.env["AZURE_STORAGE_CONTAINER"] 
|| "";

これで下準備が完了しました。

Azure Blob Storage へのアップロード

取得した画像を都度アップロードする部分を先に作成をします。まず、Azure Blob Storage につなげる手続きをまず記載します。

  const sharedKeyCredential = new StorageSharedKeyCredential(
    AZURE_STORAGE_ACCOUNT,
    AZURE_STORAGE_ACCESS_KEY
  );
  const blobServiceClient = new BlobServiceClient(
    `https://${AZURE_STORAGE_ACCOUNT}.blob.core.windows.net`,
    sharedKeyCredential
  );
  const containerClient = blobServiceClient.getContainerClient(
    AZURE_STORAGE_CONTAINER
  );

続いて取得した画像をアップロードするため、以下のようにコードを書き換えました。

  try {
    const externalApiUrl =
      NEXT_PUBLIC_PLAYWRIGHT + "/api/screenshot?url=" + url;
    const response = await axios.get(externalApiUrl);
    const imageData = response.data.screenshot;
    const decodedImageData = Buffer.from(imageData, "base64");

    const blockBlobClient = containerClient.getBlockBlobClient(
      domain + "/" + filename + ".png"
    );
    await blockBlobClient.uploadData(decodedImageData);
    console.log("Image was uploaded");

    res.setHeader("Content-Type", "image/png");
    res.status(200).end(decodedImageData, "binary");
  } catch (error) {
    return res.status(500).json({ error: "Can't get content data" });
  }

これにより、API が取得した URL を利用してスクリーンショットを作成し、ストレージにファイルを保存して、画像を表示する形に書き換える形となりました。

実際に、いくつかの URL を渡したところ、以下のようにファイルが生成されているのを確認することができました。

random desc

ファイルの有無の確認

すでに取得済みの URL に関して、ファイルがあるかどうかの確認を追加します。書き換えたコードは以下の通りです。

  try {
    const blockBlobClient = containerClient.getBlockBlobClient(
      domain + "/" + filename + ".png"
    );
    const exists = await blockBlobClient.exists();

    if (!exists) {
      const externalApiUrl = NEXT_PUBLIC_PLAYWRIGHT + "/api/screenshot?url=" + url;
      const response = await axios.get(externalApiUrl);
      const imageData = response.data.screenshot;
      const decodedImageData = Buffer.from(imageData, "base64");

      await blockBlobClient.uploadData(decodedImageData);
      console.log("Image was uploaded");

      res.setHeader("Content-Type", "image/png");
      res.status(200).end(decodedImageData, "binary");
    } else {
      const downloadResponse = await blockBlobClient.downloadToBuffer();
      console.log("file is exist");

      res.setHeader("Content-Type", "image/png");
      res.status(200).end(downloadResponse, "binary");
    }
  } catch (error) {
    return res.status(500).json({ error: "Can't get content data" });
  }

実際に実行すると、ファイルがある場合は console に file is exist というメッセージを表示して、ストレージから読み込んだ画像を表示するようになりました。スクリーンショットを撮る時は2秒待つ形で現在は構成しているため、画像の表示速度を上げる形となりました。

まとめ

複数回に分けて Playwright の利用の仕方、環境を整えてスクリーンショットを取得することが可能となりました。このスクリーンショットの画像に関して、呼び出すための API を準備して、URL を指定すれば画像が表示されるようになります。

これを利用して、Sitecore Search で結果を表示する際に、スクリーンショットを利用することが可能となりました。