はるさめ.dev

Supabase Storage に日本語を使うと Invalid Key エラー

に公開

背景

ファイルのアップロード先として Supabase Storage を使用しています。
ユーザーが選択した日本語ファイル名をそのまま使用してアップロードを試みました。しかし、以下のエラーが発生しました。

{
    "error": "Invalid Key",
    "message": "Invalid key: <例: 日本語ファイル名>"
}

解決方法

日本語ファイル名や特殊文字を含むファイル名をアップロードするには、Base64 エンコード/デコードを利用します。

ただし、btoa/atob はマルチバイト文字列に対応していません。そのため、文字列を一度シングルバイト(UTF-8 エンコード)に変換してから Base64 に変換する必要があります。

詳細については Base64 - Unicode 問題 | MDN を参照してください。

// https://github.com/supabase/storage/issues/133#issuecomment-2459780097 を参考

function base64ToBytes(base64: string) {
  const binString = atob(base64);
  return Uint8Array.from(binString, (m) => m.codePointAt(0)!);
}

function decodeBase64(base64: string) {
  try {
    return new TextDecoder().decode(base64ToBytes(encoded));
  } catch {
    return encoded;
  }
}

function bytesToBase64(bytes: Uint8Array) {
  const binString = Array.from(bytes, (byte) =>
    String.fromCodePoint(byte),
  ).join("");
  return btoa(binString);
}

function encodeToBase64(str: string) {
  return bytesToBase64(new TextEncoder().encode(str));
}

// ファイルをアップロードするとき
client.storage.from("file").upload(`${encodeToBase64(attachment.name)}`, attachment);

// ファイルを表示するとき
const result = await client.storage.from(“file").list();
const fileNames = result.data?.map(file => decodeBase64(file.name));

備考

この問題は日本語ファイル名に限らず、Amazon S3 の「Characters to avoid」に含まれる文字を使用した場合にも発生します。

Supabase Storage の内部実装は Amazon S3 を基盤としていますが、Supabase ライブラリではより厳格なチェックを行っており、エラーが発生する仕様です。

参考

コメント