WordPressのアップロードファイル名
2025.03.18
WordPressでファイルをアップロードする際にアップロードするファイルのファイル名を事前に半角英数の管理しやすいファイル名にしてアップロードするのはサイト内で使用するアップロードファイルを管理する上ではとても良い方法の一つです。
※ここで言う「ファイル名」はメディアとして投稿されたタイトル(投稿タイトル)ではなくアップロードファイルのURLと使用される「xxxx.jpg」のようなファイル名です。
ですが、投稿数が多い場合や多くの画像をアップロードしたい場合などついつい面倒になってしまうこともあるかと思います。
また、何も気にせずにファイルをアップロードする際に問題になりがちなのがマルチバイトのファイル名(日本語のファイル名)のファイルや意図せず記号が含まれたファイル名のファイルをアップロードしてしまうようなケースです。(後者の記号が含まれるファイル名のケースはあまりないかもしれませんが。)
※WordPressのデフォルトの仕様では日本語のファイル名はそのままアップロードされたファイルのファイル名として使用されます。記号についてはファイル名の先頭の記号は削除され、その他の記号は使用可能な記号であればそのままの形でファイル名として使用されます。
日本語でWordPressを運用している方の多くは「WP Multibyte Patch」というプラグインを使用されているかもしれません。(私も過去、長く利用させていただいておりました。ありがとうございます。)
このプラグインはマルチバイトの文字に対していくつかの補助機能があり、その一つに日本語のファイル名のファイルをアップロードした際にファイル名を自動的に「ca49f15f9b95aa9a7284dae2aacb195b.jpg」のような半角英数のファイル名に変換する機能があります。
この日本語ファイル名のmd5ハッシュ化は「WP Multibyte Patch」プラグインを使用しなくても簡単に実現は可能です。また、同様のコードでアップロードするファイル名を特定のルールに沿ったファイル名に変換することが可能です。
アップロードするファイルのファイル名をどのようなものにしたいかはサイト運営者の管理の仕方次第ですので自由に設定していただければと思いますが、次の点については意識された方が良いでしょう。
1. 日本語ファイル名を使用しない
2. ファイル名は半角英数の「小文字」とする
1.についてはマルチバイトの文字列(ファイル名)の取り扱いは使用するサーバーにより違いが出てくるケースがあるため、データを別サーバーに移行する際やデータのバックアップ、バックアップデータのリストア時などにまれに問題が発生するケースがあります。
2.についても大文字、小文字の取り扱いはサーバーによって違いが出てくるケースがあるのですが、アップロードファイルをFTPなどでダウンロードしてバックアップしておこうとする際にもご利用のパソコンのOS次第で大文字小文字の違いしかない二つのファイルをダウンロードすると別ファイルとして認識できず上書きしてしまい、データの欠落などを起こす恐れがあります。
※Webサーバー内では「A.jpg」と「a.jpg」が別ファイルとして存在しても、ダウンロード時に「a.jpg」(あるいは「A.jpg」)のみとなってしまう恐れがあります。
他にも手法は多々あるかと思いますが、以下のコードで特定のプラグイン等がなくてもファイルアップロード時にファイル名を変換して登録が可能となります。functions.php などに記述するだけで機能します。
下記のコードではすべてのアップロードファイルをmd5ハッシュ化して登録するような設定です。
設定部分を変更すれば、日本語ファイル名のみmd5ハッシュ化する、md5ハッシュ化ではなく投稿IDで登録する(例. 00001101.jpg)というようなことも可能です。
// Set attachment filename format before WordPress default action (Not change slug)
add_filter('sanitize_file_name', 'my_sanitize_file_name', 10, 2);
/**
* This method is used to exchange attachment filename. Not change slug and title.
* This is a filter hook of 'sanitize_file_name'.
* @param string $filename Sanitized filename.
* @param string $filename_raw The filename prior to sanitization.
* @return string
*/
function my_sanitize_file_name($filename, $filename_raw)
{
global $wpdb;
// Attachment filename format [|md5|{sprintf() format}]
$attachment_filename_format = 'md5';
// Whether to apply only multibyte file names or all file names [true|false] False applies all,
$apply_only_multibyte_filename = false;
if (!$attachment_filename_format || ($apply_only_multibyte_filename && strlen($filename) === mb_strlen($filename))) {
return $filename;
}
if (strtolower($attachment_filename_format) === 'md5') {
// Create the filename with the function md5('filename' . time()).
$filename = preg_replace('/(.*)(.[^.]+)$/', md5('$1' . time()) . '$2', $filename);
} else {
// MySQL >= 8.0
$pre_query = $wpdb->prepare('SET SESSION information_schema_stats_expiry = %d', 0);
$pre_db_result = $wpdb->query($pre_query);
if ($pre_db_result === false) {
// Create the filename with the function md5('filename' . time()), because cannot get correct post ID.
$filename = preg_replace('/(.*)(.[^.]+)$/', md5('$1' . time()) . '$2', $filename);
} else {
$results = $wpdb->get_results($wpdb->prepare('SHOW TABLE STATUS LIKE %s', $wpdb->posts));
$auto_increment = (!empty($results)) ? $results[0]->Auto_increment : 0;
$post_ID = $auto_increment;
// Create the filename with the function sprintf($attachment_filename_format . 'post ID').
$alt_post_name = strtolower(sprintf($attachment_filename_format, $post_ID));
$filename = preg_replace('/(.*)(.[^.]+)$/', $alt_post_name . '$2', $filename);
}
}
return $filename;
}
2行目 sanitize_file_nameフックを利用します。
15行目 ファイル名をどのようなフォーマットに変換するかの設定部分です。
''(空の文字列)を設定するとWordPressデフォルトのアクションになります。
'md5' を設定するとファイル名をmd5ハッシュ化します。ファイル名とアップロード日時(Timestamp)を使用してmd5ハッシュ化します。
'%08d' のようなPHPのsprintf()の第1引数にあたる文字列を設定するとsprintf()と投稿IDを使用してファイル名を変換します。(例. 00001101.jpg)
17行目 ファイル名の変換をアップロードファイル名がマルチバイト(例えば日本語)のファイル名にのみ適用するか、すべてのファイルに適用するかを設定します。
true マルチバイト(例えば日本語)のファイル名にのみ適用
false すべてのファイルに適用
注意事項 1
15行目で'%08d'のようなsprintf()の第1引数文字列を指定した場合、26-27行目でファイル名の変換前にデータベースのオートインクリメント値を取得してアップロードファイルの投稿IDとしています。
この処理で何らかの影響でエラーが起き、オートインクリメント値を取得できなかった場合には強制的にファイル名とアップロード日時(Timestamp)を使用したmd5ハッシュをファイル名としています。
MySQL 8.0 以降はINFORMATION_SCHEMAに保存されたTABLES.AUTO_INCREMENTを取得するため正確なオートインクリメント値が取得できない場合があります。
26-27行目は正しいオートインクリメント値を取得するための処理です。
注意事項 2
15行目で指定した文字列が、sprintf()の第1引数の文字列として適正であるかどうかのチェックは行っておりませんのでご注意ください。
参考
PHP sprintf()
WP Multibyte Patch プラグイン
WP Multibyte Patch 作者 ドキュメント
MySQL 8.0 INFORMATION_SCHEMA クエリーの最適化