半年に 1 回ぐらい Azure Storage Blob を触るんだけど、毎回 Content-Type をセットするのを忘れてハマっている。
今回は nodejs で書いたので、忘れないようにメモ。

パッケージとして @azure/storage-blob を使う。あとファイル検索のために glob もつかう。


npm install -S @azure/storage-blob glob

とりあえずファイルをアップロードするサンプル。


const mime = require("mime");
const { BlobServiceClient } = require("@azure/storage-blob");

const AZURE_STORAGE_CONNECTION_STRING = "DefaultEndpointsProtocol=https;AccountName=xxxx;AccountKey=xxxxx;EndpointSuffix=core.windows.net";
const fileName = "./file.html";
const containerName = "$web";

async function uploadToBlob(fileName) {
  const blobServiceClient = await BlobServiceClient.fromConnectionString(
    AZURE_STORAGE_CONNECTION_STRING
  );

  const containerClient = await blobServiceClient.getContainerClient(
    containerName
  );

  const blockBlobClient = containerClient.getBlockBlobClient("file.html");
  const data = fs.readFileSync(fileName);
  const contentType = mime.getType(fileName);
  const options = {
    blobHTTPHeaders: {
      blobContentType: contentType,
    },
  };

  return await blockBlobClient.upload(data, data.length, options);
}

uploadToBlob(fileName)
  .then((result) => console.log(result))
  .catch((e) => console.error(e));

ポイントは mime で Content-Type を判別して、blobContentType に突っ込む、ってこれ普通に node やってる人からしたあたりまえなのかな。公式サンプル無いのなんでなんだろ… すごい悩んだ。

まとめてアップロードする時は glob 使ってこんな感じ。


async function uploadFolderToBlob() {
  const blobServiceClient = await BlobServiceClient.fromConnectionString(
    AZURE_STORAGE_CONNECTION_STRING
  );

  const containerClient = await blobServiceClient.getContainerClient(
    containerName
  );

  return Promise.all(
    glob("./public/**/*.*", { nodir: true, sync: true }).map(async (fileName) => {
      console.log(fileName);
      const blockBlobClient = containerClient.getBlockBlobClient(fileName);
      const data = fs.readFileSync(fileName);
      const contentType = mime.getType(fileName);
      const options = {
        blobHTTPHeaders: {
          blobContentType: contentType,
        },
      };
      return await blockBlobClient.upload(data, data.length, options);
    })
  );
}

uploadFolderToBlob()
  .then((results) => console.log(results))
  .catch((e) => console.error(e));

Promise.all() で Promise のリストを包んでやるのがポイント。相変わらず非同期処理の書き方が分かってないので、いつもググりながら書いてる。
試した感じ fileName が ./path/to/file みたくなっても、いい感じにアップロードしてくれるらしい。
(上記の例だと $web/path/to/file にアップロードされる)

今年も 1/3 が終わってしまった。そろそろ Azure AD B2C のカスタム ポリシーのまとめネタを書きたいけど、相変わらず全然わからんのでちょいネタでブログ更新。