Mac OS と s3 と日本語ファイル名

AWS の S3 + CloudFront でサイトを運用していると、日本語ファイル名の中に、濁音、半濁音を含まれていると Web ブラウザからアクセスできないこと気付きました。原因は Mac OS の HFS+ が NFD (の亜種) ユニコードで、 Web ブラウザからのリクエストは NFC ユニコードであるためでした。 (参考: ikeikeikeike’s unk blog. : Macの濁点問題を解決するPython unicodedataモジュール )

説明

Mac から AWS CLI を使ってファイルを s3 にアップロードした場合、s3 上のオブジェクト名は NFD ユニコードのまま URL エンコーディングされたものになります。NFD は HFS+ の事情ですので、 s3 アップロード時点で標準的な NFC ユニコードに変換するのが望ましいのですが、そちらは AWS CLI の ISSUE で話題に上がってましたので、いずれ解決するのを待つとして、当面の間は Python Fabric を使って、アップロード後に NFC ユニコードにリネームすることにしました。

準備

Fabric と AWS CLI をインストールします。

$ pip install fabric awscli

コード

fabfile.py のコードは次の通りです。

# -*- coding: utf-8 -*-

from __future__ import unicode_literals, print_function, division

import os
from unicodedata import normalize

AWS = {
  'S3Bucket': '<xxxxxx>'  # <-- Bucket 名を設定する
}

@task
def rename(path):
  for name in os.listdir('{path}'.format(path=path)):
    rename = normalize('NFC', name)
    if name != rename:
      cmd = 'aws s3 mv s3://{bucket}/{path}/{name} s3://{bucket}/{path}/{rename}'.format(
        bucket=AWS['S3Bucket'],
        path=path,
        name=name,
        rename=rename)

      # print(cmd)
      locale(cmd)
  • 指定したローカルディレクトリ内を調べ、 NFC に変換する必要のあるファイル名の mv コマンドを発行します。
  • コンソールに表示される変換前後の名称は同じに見えますが、内部表現は NFD, NFC ですので、正しくリネームされます。

使い方

$ fab rename:tags

tags ディレクトリにある濁音、半濁音を含むファイル名が NFC ユニコードにリネームされます。