file upload 総まとめ

そもそも、日本語表示や input type=file の挙動についての調査は、仕事で使っている groupware のドキュメント管理機能の file 登録画面が発端だったのだ。その画面では input type=file を使って local file をサーバに送る機能を持っていて、サーバ上での file name は user が指定するようになっている。で、default file name として、input type=file が掴んだ path の file name 部分を切り取って使うようになっている。ただし、パスの区切り文字が "\\" と hard coding されているというダメな作りだった。当然 Windows 環境以外では軒並コケる。(^^;;  この groupware の user(になる予定の人達)は半数近くが Macintosh user のはずなので、これでは当然困る。そこで Mac 対応を…となったわけです。つまり本来の目標は、file name の default をそれらしく作ること。それだけだったのだ。これは、OS と browser で条件分岐してやれば、別になんてことはない…はずだった。でも、Mac 版 IE でハマりました。user 多そうなんで見なかったことにできないのだ。

でまぁ、追いかけ始めてしまったものはしょうがないので、さらに追いました。その結果、Mac 版の IE の中がどうダメかが見えてきたので、まとめておこうと。そういうページです。ここに至るまでの副産物が 「alert window への日本語表示」と 「input type=file の file path 文字列」 だったのです。実は。

IE が JavaScript engine に渡す file path 文字列

input type=file の file path 文字列」では SJIS で 0x8FEE である「情」が、Mac 版 IE の escape() によって %uFF8F%uFFEE に変換されると書いた。これに関して、今度は String.charCodeAt() メソッドで文字コードを確認することにした(下の form)。まず input type=text で試してみると、「情」に対して 0x60C5 が返ってきた。規格通りに UCS-2 の文字コードになっている。同じことを input type=file で試してみると、「情」に対して -0x71, -0x12 の二つの値が返された。このことから「情」が 2byte の1文字として扱われていないことが分かった。また、二つの値にそれぞれ 0xFF を足すと 0x8F, 0xEE になり、これは「情」の SJIS の文字コードにあたる。どこかで char が signed int として扱われてるのかも知れない。そう考えると、escape() の返り値が %uFFE8%uFFEE などとなる現象も、なんとなく納得できる。

まぁとにかく input type=file からは、日本語は SJIS ベースの扱いで JavaScript engine に渡されているらしいことと、2byte 文字への対応がほぼ無視されているらしいことが判明した。下の form で確認できます。

 → 
 → 

JavaScript engine が出力する文字列

次に、JavaScript engine に日本語文字列を出力させる方法を確認してみた。script 内部に alert( "情" ); などと生の文字列を埋め込んだ場合には、問題なく出力できるようだ。これは文字列の扱いが JavaScript 内部で完結しているためだろう。一方、HTML 内で引数として文字列を渡した場合には、いろいろと問題が起こることが分かっている(alert window への日本語表示)。今回の目的である path 文字列の処理では、必ずこのタイプになる。

この場合、String.fromCharCode() を利用して文字列を出力することになる(他に手があったら教えてください)が、str = String.fromCharCode( 0x8FEE ); document...value = str; などとすると文字化けが起きた。String.fromCharCode() の引数を 0x8 << 12 | 0xF << 8 | 0xE << 4 | 0xE などとしても(当然)ダメだった。それに対して str = String.fromCharCode( 0x60C5 ); document...value = str; では「情」が出力され、String.fromCharCode() が引数を UCS-2 として扱っていることが確認できた。

ということで…

Mac 版 IE の JavaScript 処理においては、入力された文字列は(崩れた)SJIS として扱われるが、文字列を出力する場合には UCS-2 として扱われているらしい。したがって、受け取った文字列を正しく表示させるためには、SJIS → UCS-2 のコード変換が必要になることが分かった。SJIS の文字コードは読み順が基本になっているのに対して、UCS-2 では部首順(部品順?)が基本になっており、この変換のためには対応表を抱える必要がある。対応表の。obsolete だそうですが。

で、言うまでもないことではありますが、普通はこういう状況では対応をあきらめます。でも、それはちょっと寂しいので、無理矢理コード変換を実装してみたのだ。これはこれでむなしいけど、まぁ試してみてください


[ JavaScript のブラウザ依存性 ] [ HTML 入門 ] [ 大' 小屋 ]
御意見御感想は「けいじわん」(WebBBS) までどうぞ。
satodai@dog.intcul.tohoku.ac.jp