Movable Type + Windows で日本語ファイル名を扱う方法
Movable Type を Windows で運用し、日本語ファイル名を扱うための方法です。ここでは Movable Type 4.25 を使ったカスタマイズを紹介します。
1.概要
Movable Type デフォルトの状態では、Window 上に構築した Movalbe Type で日本語ファイル名を扱うことはできません(仕様です)。
例えば、「コーヒーカップ.jpg」というファイルをアップロードすると、アップロード自体はできますが、アイテム一覧は次のように、アップロードした画像が表示されません(同じ画像のcoffee.jpgと比較)。画像のリンクをクリックしても 404 Not Found になります。
![]()
半角英数ファイル名の画像をクリックすると拡大画像を次のように表示できますが、
![]()
日本語ファイルでは表示されません。
![]()
サムネイルも正常に表示されません。
![]()
ブログ記事への挿入は、半角英数ファイル名であれば正常に挿入できますが、
![]()
日本語ファイルでは正常に挿入できません。
![]()
アップロードしたファイルをエクスプローラーで参照すると、次のように文字化けしています。

asset_c 配下のサムネイルやキャッシュファイルも文字化けしています。

ということで、本エントリーでは、ファイルのアップロード時にファイル名を Shift_JIS で保存し、アイテム一覧などでのファイル名操作での文字コードを修正して、日本語ファイル名を正常に処理できるようにカスタマイズする方法を以下に紹介します。
2.カスタマイズ
カスタマイズは、パッチを利用して、lib/MT 配下の4つのファイルを修正します。パッチが分からない方は、手修正できる方法も併せて掲載しています。なお、修正対象のファイルは、修正前に必ずバックアップを保存してください。
lib/MT/FileMgr/Local.pm
lib/MT/FileMgr/Local.pm を修正します。修正目的は次の通りです。
- ファイルアップロード時の元ファイル名の文字コード変更
 - 元ファイルの削除時のファイル名の文字コード変更
 
--- lib/MT/FileMgr/Local.pm.bak        Fri May 22 01:48:47 2009
+++ lib/MT/FileMgr/Local.pm    Fri May 22 01:49:05 2009
@@ -12,6 +12,7 @@
 
 use Symbol;
 use Fcntl qw( :DEFAULT :flock );
+use Jcode;
 
 sub get_data {
     my $fmgr = shift;
@@ -68,6 +69,7 @@
         $perms = $cfg->HTMLPerms;
     }
     my $old = umask(oct $umask);
+    $to = jcode($to)->sjis;
     sysopen FH, $to, O_RDWR|O_CREAT|O_TRUNC, oct $perms
         or return $fmgr->error(MT->translate(
             "Opening local file '[_1]' failed: [_2]", $to, "$!"));
@@ -165,7 +167,7 @@
 sub delete {
     my $fmgr = shift;
     my ($file) = @_;
-
+    $file = jcode($file)->sjis;
     return 1 unless -e $file or -l $file;
     unlink $file
        or return $fmgr->error(MT->translate(
パッチが分からない方は下記の青色部分を追加してください。
...前略...
use Symbol;
use Fcntl qw( :DEFAULT :flock );
use Jcode;
...中略...
sub _write_file {
    my $fmgr = shift;
    my($from, $to, $type) = @_;
    local *FH;
    my($umask, $perms);
    my $cfg = MT->config;
    if ($type && $type eq 'upload') {
        $umask = $cfg->UploadUmask;
        $perms = $cfg->UploadPerms;
    } else {
        $umask = $cfg->HTMLUmask;
        $perms = $cfg->HTMLPerms;
    }
    my $old = umask(oct $umask);
    $to = jcode($to)->sjis;
    sysopen FH, $to, O_RDWR|O_CREAT|O_TRUNC, oct $perms
        or return $fmgr->error(MT->translate(
            "Opening local file '[_1]' failed: [_2]", $to, "$!"));
...中略...
sub delete {
    my $fmgr = shift;
    my ($file) = @_;
    $file = jcode($file)->sjis;
    return 1 unless -e $file or -l $file;
...後略...
lib/MT/Asset/Image.pm
lib/MT/Asset/Image.pm を修正します。修正目的は次の通りです。
- アイテムが画像の場合、オプションでサムネイルを指定した場合など、サムネイルのファイル名の文字コード変更
 
--- lib/MT/Asset/Image.pm.bak  Fri May 22 01:48:42 2009
+++ lib/MT/Asset/Image.pm      Fri May 22 01:49:10 2009
@@ -8,6 +8,7 @@
 
 use strict;
 use base qw( MT::Asset );
+use Jcode;
 
 __PACKAGE__->install_properties( {
     class_type => 'image',
@@ -91,7 +92,8 @@
     my $asset     = shift;
     my (%param)   = @_;
     my $file_path = $asset->file_path;
-    my @imginfo   = stat($file_path);
+    my $file_path2 = jcode($file_path)->sjis;
+    my @imginfo   = stat($file_path2);
     return undef unless @imginfo;
 
     my $blog = $param{Blog} || $asset->blog;
@@ -153,7 +155,7 @@
 
         # create a thumbnail for this file
         require MT::Image;
-        my $img = new MT::Image( Filename => $file_path )
+        my $img = new MT::Image( Filename => $file_path2 )
           or return $asset->error( MT::Image->errstr );
 
         # Really make the image square, so our scale calculation works out.
パッチが分からない方は下記の赤色部分を削除し、青色部分を追加してください。
...前略...
use strict;
use base qw( MT::Asset );
use Jcode;
...中略...
sub thumbnail_file {
    my $asset     = shift;
    my (%param)   = @_;
    my $file_path = $asset->file_path;
    my @imginfo   = stat($file_path);
    my $file_path2 = jcode($file_path)->sjis;
    my @imginfo   = stat($file_path2);
    return undef unless @imginfo;
...中略...
    else {
 
        # create a thumbnail for this file
        require MT::Image;
        my $img = new MT::Image( Filename => $file_path )
        my $img = new MT::Image( Filename => $file_path2 )
          or return $asset->error( MT::Image->errstr );
...後略...
lib/MT/Asset.pm
lib/MT/Asset.pm を修正します。修正目的は次の通りです。
- キャッシュファイル(asset_c 配下のサムネイル画像)の削除時のファイル名の文字コード変更
 
--- lib/MT/Asset.pm.bak        Thu Mar 12 05:41:04 2009
+++ lib/MT/Asset.pm    Fri May 22 01:43:30 2009
@@ -9,6 +9,7 @@
 use strict;
 use MT::Tag; # Holds MT::Taggable
 use base qw( MT::Object MT::Taggable MT::Scorable );
+use Jcode;
 
 __PACKAGE__->install_properties({
     column_defs => {
@@ -182,6 +183,7 @@
                 my $basename = $asset->file_name;
                 my $ext = '.'.$asset->file_ext;
                 $basename =~ s/$ext$//;
+                $basename = jcode($basename)->sjis;
                 my $cache_glob = File::Spec->catfile($cache_dir,
                     $basename . '-thumb-*' . $ext);
                 my @files = glob($cache_glob);
パッチが分からない方は下記の青色部分を追加してください。
...前略...
use strict;
use MT::Tag; # Holds MT::Taggable
use base qw( MT::Object MT::Taggable MT::Scorable );
use Jcode;
...中略...
sub remove_cached_files {
    my $asset = shift;
 
    # remove any asset cache files that exist for this asset
    my $blog = $asset->blog;
    if ($asset->id && $blog) {
        my $cache_dir = $asset->_make_cache_path;
        if ($cache_dir) {
            require MT::FileMgr;
            my $fmgr = $blog->file_mgr || MT::FileMgr->new('Local');
            if ($fmgr) {
                my $basename = $asset->file_name;
                my $ext = '.'.$asset->file_ext;
                $basename =~ s/$ext$//;
                $basename = jcode($basename)->sjis;
                my $cache_glob = File::Spec->catfile($cache_dir,
                    $basename . '-thumb-*' . $ext);
...後略...
lib/MT/CMS/Asset.pm
lib/MT/CMS/Asset.pm を修正します。修正目的は次の通りです。
- アイテム一覧でアイテムを正常に取得・表示するための文字コード変更
 - title属性に日本語を適正に表示するため、文字コードをUTF-8に戻す
 
--- lib/MT/CMS/Asset.pm.bak    Thu Feb 05 18:49:50 2009
+++ lib/MT/CMS/Asset.pm        Fri May 22 01:44:48 2009
@@ -3,6 +3,7 @@
 use strict;
 use Symbol;
 use MT::Util qw( epoch2ts encode_url format_ts relative_date );
+use Jcode;
 
 sub edit {
     my $cb = shift;
@@ -590,10 +591,12 @@
         $row->{asset_type} = $obj->class_type;
         $row->{asset_class_label} = $obj->class_label;
         my $file_path = $obj->file_path; # has to be called to calculate
+        $file_path = jcode($file_path)->sjis;
         my $meta = $obj->metadata;
         if ( $file_path && ( -f $file_path ) ) {
             $row->{file_path} = $file_path;
             $row->{file_name} = File::Basename::basename( $file_path );
+            $row->{file_name} = jcode($row->{file_name})->utf8;
             my @stat = stat( $file_path );
             my $size = $stat[7];
             $row->{file_size} = $size;
パッチが分からない方は下記の青色部分を追加してください。
...前略...
use strict;
use Symbol;
use MT::Util qw( epoch2ts encode_url format_ts relative_date );
use Jcode;
...中略...
sub build_asset_hasher {
    my $app = shift;
    my (%param) = @_;
    my ($default_thumb_width, $default_thumb_height, $default_preview_width,
        $default_preview_height) =
        @param{qw( ThumbWidth ThumbHeight PreviewWidth PreviewHeight )};
 
    require File::Basename;
    require JSON;
    my %blogs;
    return sub {
        my ( $obj, $row, %param ) = @_;
        my ($thumb_width, $thumb_height) = @param{qw( ThumbWidth ThumbHeight )};
        $row->{id} = $obj->id;
        my $blog = $blogs{ $obj->blog_id } ||= $obj->blog;
        $row->{blog_name} = $blog ? $blog->name : '-';
        $row->{url} = $obj->url; # this has to be called to calculate
        $row->{asset_type} = $obj->class_type;
        $row->{asset_class_label} = $obj->class_label;
        my $file_path = $obj->file_path; # has to be called to calculate
        $file_path = jcode($file_path)->sjis;
        my $meta = $obj->metadata;
        if ( $file_path && ( -f $file_path ) ) {
            $row->{file_path} = $file_path;
            $row->{file_name} = File::Basename::basename( $file_path );
            $row->{file_name} = jcode($row->{file_name})->utf8;
            my @stat = stat( $file_path );
...後略...
3.修正後の動作
アイテム一覧で画像が正常に表示されます。

拡大画像も正常に表示されます。

アップロードしたファイルをエクスプローラーで参照すると、次のように日本語が適正に表示されます。

asset_c 配下のサムネイルやキャッシュファイルも適正に表示されています。

ブログ記事への挿入もOKです。

サムネイルも表示されます。

4.注意事項
- サムネイルの拡大画像が表示されません(分かり次第追記します)。
 - 確認しているのは、テキストファイルと画像ファイルのみです。音声・動画ファイルの動作は未確認です。
 - FastCGI を利用していると正常に動作しません。
 
- Movable Typeで特定の拡張子のファイルをアップロードする方法
 - 特定のアイテムのみをブログ記事に表示する
 - Movable Typeのブログ記事で未使用のアイテム一覧を表示する(本文未挿入版)
 - Movable Typeの管理サイトでFTPが使えないときにファイルをアップロードする裏ワザ
 - Movable Typeのブログ記事で未使用のアイテム一覧を表示する
 - サムネイルリストから不要な右マージンを除去する
 - Movable Type 5 でスライドショーを実現する(その2:応用)
 - MTAssetThumbnailLinkタグとMTAssetThumbnailURLタグのsquareモディファイアの動作
 - Movable Type のブログ記事に表示する画像のサイズを制御する
 - Movable Type 4 におけるアイテムのアップロード動作(その2)
 - Movable Type 4 におけるアイテムのアップロード動作(その1)
 - ブログ記事に挿入したアイテムだけのサムネイル画像一覧を表示する(その2)
 - ブログ記事に挿入したアイテムだけのサムネイル画像一覧を表示する
 
>oscarさん
こんばんは。
はい、ここでこのシリーズは終了です。
ちなみに Linux であればデフォルトで大丈夫みたいです。
