WordPressサイト で一部の .xlsファイル だけがアップロードできない現象に遭遇したため、対処しました。
現象
とある WordPressサイト で .xlsファイル をアップロードしようとすると以下のエラーが表示されました。
“XXXXXXXXXXX.xls” のアップロードに失敗しました。
このファイルタイプはセキュリティ上の理由から、許可されていません。

しかも困ったことに、「Aの .xlsファイル はOKだが、Bの .xlsファイル はNG」というように、ファイルによって現象が分かれました。
両方とも正常に開ける .xlsファイル ですし、見た目上は同じなのですが……。
対処1
最初の対処として、 wp-config.php にファイルアップロードの際のフィルタリングをオフにする方法を試しました。
<?php
// 略
$table_prefix  = 'wp_';
// 略
define('WP_DEBUG', false);
define('ALLOW_UNFILTERED_UPLOADS', true); // この1行を追記
/* 編集が必要なのはここまでです ! WordPress でブログをお楽しみください。 */
// 略これでファイルアップロードを試したところ、2つの .xlsファイル 共にアップロードできるようになりました。
ただし、この方法ですとファイルアップロードの際のフィルタ処理を全てオフにしてしまうため、セキュリティ的に好ましくありません。
そこで、もう少し調査を続けることにしました。
検証
上述の対処1より、ファイルアップロードの際のフィルタリング処理で引っかかっていることは分かりました。
このフィルタリングは、拡張子と MIMEタイプ の判定をしているということが分かりました。
ファイルとしては、 wp-includes/functions.php です。
中身を見て、関数 wp_get_mime_types() で拡張子と MIMEタイプ の一覧を持っていることが分かります。
この処理にアクションフックを引っかけることができれば良さそうです。
MIMEタイプ の確認
次に、問題のファイルの MIMEタイプ を確認します。
試しに、以下のような構成を作ります。
   /
  ├ files/
  │    ├ sample1.xls  // ファイルアップロード OK の .xlsファイル
  │    └ sample2.xls  // ファイルアップロード NG の .xlsファイル
  │
  └ index.phpまた、 index.php を
この記事を参考にして、以下のようにします。
<?php
$paths = [
    './files/sample1.xls',
    './files/sample2.xls',
];
// finfoクラスを使う
$finfo = new finfo();
foreach ($paths as $key => $value) {
    echo $value . ": ";
    echo $finfo->file( $value, FILEINFO_MIME_TYPE );
    echo "<br><br>\n\n";
}これを問題が発生している WordPressサイト と同じサーバにアップロードします。

すると、ファイルアップロード OK の .xlsファイルは MIMEタイプが application/vnd.ms-excel だったのに対し、 NG だった .xlsファイル は application/vnd.ms-office でした。

ちなみに、他の環境に同じファイル群をアップロードしたところ両方とも application/vnd.ms-excel で、この環境では今回の現象は発生しませんでした。
MIMEタイプ は .xls の場合 application/vnd.ms-excel のはずですが……。
先に結論から言ってしまえば、利用しているサーバーのPHPのバージョンが低く、PHPの中で呼び出される「Fileinfo」というファイル操作のモジュールのバージョンが低かった為、アップロードしたエクセルファイルの正しいMIMEタイプが認識がされていないという状態になっていました。
PHP のバージョンによって Fileinfoモジュール の判定結果が異なるとのこと。 WordPress の MIMEタイプ 判定もこのモジュールを得利用しているとのことで、ここで影響を受けてしまうようです。
以上より、今回の環境では本来 application/vnd.ms-excel となるべき MIMEタイプ が、何故か application/vnd.ms-office と判定され、結果、 WordPress のファイルアップロードの際のフィルタリング処理の中の MIMEタイプ 判定で引っかかっていた、というのが今回の現象の原因でした。
対処2
以上の検証を踏まえて対処をします。具体的には、アクションフックでファイルアップロードの際のフィルタリング処理の際に application/vnd.ms-office も許可するようなプラグインを作成します。
<?php
/*
Plugin Name: MIMEUruwashii
Description: PHP の MIME タイプ判定で特定の .xlsファイル が弾かれる現象への対策
Version: 0.0.1
Author: アルム=バンド
*/
/**
 * MIMEUruwashii : PHP の MIME タイプ判定で特定の .xlsファイル が弾かれる現象への対策
 * 
 */
class MIMEUruwashii
{
    /**
     * __construct : コンストラクタ
     *
     */
     public function __construct() {
        add_filter(
            'upload_mimes',
            [
                $this,
                'Bibishii',
            ]
        );
    }
    /**
     * Bibishii : フィルター追加
     *
     * @param {Object} : MIMEタイプ の一覧のオブジェクト
     * 
     * @return {Object} : 誤判定している MIME タイプを追記する
     *
     */
    public function Bibishii ( $mimes )
    {
        $mimes['xls'] = 'application/vnd.ms-office';
        return $mimes;
    }
}
// instantiate
$ab_wp_plugin_mimeuruwashii = new MIMEUruwashii();このプラグインを .zip でアップロード、インストールして有効化します。
もちろん、 wp-config.php の ALLOW_UNFILTERED_UPLOADS の行は削除して試験しました。
……が、挙動は変わらず、解決できませんでした。
参考
ALLOW_UNFILTERED_UPLOADS
- WordPressの「セキュリティ上の理由によりこのファイル形式は許可されません」エラーの処理方法
- WordPressのメディアにアップロードが出来ない時 | スタッフブログ | 株式会社クーネルワーク
WordPress 内のファイルアップロードのフィルタ処理について
- 【WordPress】アップロード可能なファイル拡張子を増やす | deep-space.blue
- WordPress/functions.php at master · WordPress/WordPress · GitHub
 
					 アルム=バンド
		アルム=バンド