【未解決】Opera で日本語名ファイルをアップロードすると送信される filename が文字化けする場合がある


Opera で日本語名ファイルをアップロードすると送信される filename が文字化けする場合がある。
しかしなぜか同じように送っても文字化けしないファイルもある。

原因も再現条件も分からないが、とりあえず現象レポート。

基本のおさらい

フォーム送信

ファイルを送信する時は、フォームの enctype を「multipart/form-data」に指定する。

<form name=”form1″ method=”post” action=”show_postdata.cgi” ENCTYPE=”multipart/form-data”>

file:<input type=”file” name=”uploadFile”/><br />
テキストフィールド:<input type=”text” name=”textfield”/><br />

<input type=”submit” value=”OK”/>
</form>

送信される内容

送信される形式は以下のようになる。(受け取り側のCGIで標準入力をそのまま書き出したもの。)

—————————–36022435010291
Content-Disposition: form-data; name=”uploadFile”; filename=”アップロードファイル.txt”
Content-Type: text/plain

この行からファイルの中身です。
あああ
ファイルはバイナリの場合もあります。
この行までファイルの中身です。
—————————–36022435010291
Content-Disposition: form-data; name=”textfield”

テキスト値
—————————–36022435010291–

ファイル名

送信された「filename=”アップロードファイル.txt”」の値をサーバ上のCGIプログラムなどでファイル名として解釈するのだが、この送信内容を作成しているのは送信元のブラウザの方なので、微妙に形式が異なる。

上記は Firefox の例だが、たとえば IE だとこの部分は

filename=”C:\Documents and Settings\user\デスクトップ\アップロードファイル.txt”

とローカルパスを付けた状態で送信してくる。(セキュリティ上どうかと思うけど、とりあえず不問。)

日本語ファイル名

最近のブラウザの場合大抵、ファイル名が日本語文字の場合、そのファイル名はフォームのページの文字コードで送信してくる。テキスト入力フィールドがある場合、テキストフィールドと同じ文字コードとなると思えばよい。
例えばフォームのページが Shift_JIS なら、ファイル名も Shift_JIS でのコード列になるし、ページが UTF-8 なら同じファイル名を UTF-8 コード列で送ってくる。
ただしこれもブラウザ依存なので、旧いブラウザだと必ずしもそうでない。

そして、日本語には「Shift_JIS」という、Perl プログラマにとっては厄介な文字コードがある。
Shift_JIS の場合、「表」や「申」や「ソ」の一部にIEが送ってくるローカルパス区切りの「\」であり、かつ Perl にとっては特殊文字である「\」を含んでいるのだ。

「申請書.doc」とか「分析結果表.xls」などのファイル名をブラウザはどう送ってくるか?

概要としては、以下の通り。

Firefox

ファイル名だけを、そのまま送ってくる。
例)filename=”申請書.doc”

IE

ファイルパスを含めて、そのまま送ってくる。
例)”C:\Documents and Settings\user\デスクトップ\申請書.doc”

この場合「申」の中にパス区切り「\」が含まれているので、プログラムで単純にファイル名を取り出してしまうと「請書.doc」というファイル名になるので注意が必要になる。

Opera

問題の Opera さんはファイル名だけを、特殊文字をエスケープして送ってくる。
例)filename=”申\請書.doc”

今回起きた問題

ということで、Opera はファイル名を自分なりに解釈してから送ってくれるらしいのだが、ファイル名によっては変な風にエンコードして送ってくる事が分かった。
どのエンコーディングスキームにも該当しないような不可解なコード列を送ってくる。
特定の文字列がある時という訳ではなく、何かの相互作用なようなのだが、不明。

参考データ表.xls –>OK
参考データ表.txt –>OK
参考.txt –>NG
参考表.txt –>NG
参考申請書.docx –> NG

例えば、「参考データ表.xlsx」をアップロードしてファイル名を unpack(”H*” , $filename) で見ると

8e51 8d6c 8366 815b 835e 955c5c 2e 78 6c 73 78

と期待どおりの結果になる。(Shift_JISフォーム。結果は分かち書き。以下同様。)

ところが「参考.txt」をアップロードして同様に処理すると

c3a5c3a8 2e 74 78 74

となる。

「参考申請書.docx」 だと

e89cbf e3828a efbfbd efbfbd e7ad8f e99ab2 e58cba e5b68c 2e 64 6f 63 78

となる。
途中で2回続けて現れる「efbfbd」は「Unicode には無い文字です」の「U+FFFD (REPLACEMENT CHARACTER) 」の UTF-8 での表現だけど…うーん?

これらの問題は、ファイルを2つ一緒に送信しても、「参考データ表.xls」の方はOK、「参考申請書.docx」 の方はNGと、文字化けするということ自体は再現性がある。
おまけに、EUC-JP フォームでも、Shift_JISフォームの場合と同じファイル名が文字化けした。OS(WinXP) の文字コードからの変換との関係かも知れない。
Mac (OS 10.2 )の場合、やはりOpera と NC ( Netscape Communicator )が別のパターンで文字化けした。

タグ:

コメントは受け付けていません。