[Python] Amazon S3のオブジェクトキーとして安全な文字列に変換する

こんにちは。サービス部の武田です。Amazon S3のオブジェクトキーの命名に関するガイドラインは見たことがあるでしょうか。一部の文字はURLエンコードすることが推奨されています。
2023.05.27

こんにちは。サービス部の武田です。

ファイルをS3バケットに保存しようとした際に、それがオブジェクトキーとして問題ない名前になっているか気になったことはないでしょうか。

AWSのドキュメントでは、オブジェクトキーの命名に関するガイドラインがあります。

オブジェクトキー名の作成 - Amazon Simple Storage Service

変換せずに安全に使用できる文字は0-9a-zA-Zに加え、!-_.*'()の8文字です。

またそのままでは使用できない可能性のある文字としては、制御文字を除くと&$@=;/:+ ,?の11文字です(空白を含む)。

これらの文字が含まれる場合は、問題が起きないようにURLエンコード(パーセントエンコード)をするのが望ましいです。

PythonでURLエンコード

PythonでURLエンコードするにはurllib.parse.quote関数を使用します。試しにそのまま使ってみます。

>>> import urllib.parse
>>> urllib.parse.quote("!-_.*'()09azAZ&$@=;/:+ ,?")
'%21-_.%2A%27%28%2909azAZ%26%24%40%3D%3B/%3A%2B%20%2C%3F'

これを見ると、安全に使用できる文字も変換している一方で、/が変換されていないことがわかります。これはquote関数のデフォルト動作で/は変換されないためです。また-_.についてはquote関数は変換しません。

というわけで、safe引数を指定し、この問題を解決しましょう。次のように実行します。

>>> urllib.parse.quote("!-_.*'()09azAZ&$@=;/:+ ,?", safe="!*'()")
"!-_.*'()09azAZ%26%24%40%3D%3B%2F%3A%2B%20%2C%3F"

意図した動作になりました!

結論

PythonでS3のオブジェクトキーとして安全な文字列に変換したい場合はurllib.parse.quote(string, safe="!*'()")を実行しましょう。

なおドキュメントには使用すべきでない文字もまとめられています。システムで生成する場合は気をつけ、もし外部からキー名を受け取るのであればバリデーションでチェックするようにするとよいでしょう。