ああ、文字エンコードの喜び!
ここで起こっていることは次のとおりです。Rubyは、抽出した文字列を、ファイル名のutf-8エンコーディングであるバイトシーケンスとして内部的に保存しています。これを呼び出すURI.escape
と、それらのバイトは%xy
フォーマットでエスケープされ、結果の文字列は現在ASCII範囲のバイトのみで構成されており、URLとして使用されます。
ただし、受信サーバーは、これらのバイトを(%xy
フォームからエスケープ解除した後)別のエンコーディング(この場合はISO-8859-1 )であるかのように解釈しているため、結果として得られるファイル名は、それが持っているものと一致しません。 。
これは、Ruby 1.9を使用したデモンストレーションです。これは、エンコーディングのサポートが優れているためです。
1.9.3-p194 :003 > f
=> "ÖÇÄÜ360ÓïÒôÖúÀí.txt"
1.9.3-p194 :004 > f.encoding
=> #<Encoding:UTF-8>
1.9.3-p194 :005 > URI.escape f
=> "%C3%96%C3%87%C3%84%C3%9C360%C3%93%C3%AF%C3%92%C3%B4%C3%96%C3%BA%C3%80%C3%AD.txt"
1.9.3-p194 :006 > g = f.encode 'iso-8859-1'
=> "\xD6\xC7\xC4\xDC360\xD3\xEF\xD2\xF4\xD6\xFA\xC0\xED.txt"
1.9.3-p194 :007 > g.encoding
=> #<Encoding:ISO-8859-1>
1.9.3-p194 :008 > URI.escape g
=> "%D6%C7%C4%DC360%D3%EF%D2%F4%D6%FA%C0%ED.txt"
したがって、この場合の解決策は、文字列をエスケープする前にISO-8859-1としてエンコードすることです。Ruby 1.9では、上記のようにこれを行います。以前のバージョンでは、Iconvを使用できます(JRubyにはIconvが含まれていると思いますが、実際にはJRubyにあまり詳しくありません)。
1.8.7 :001 > f
=> "\303\226\303\207\303\204\303\234360\303\223\303\257\303\222\303\264\303\226\303\272\303\200\303\255.txt"
1.8.7 :005 > g = Iconv.conv('iso-8859-1', 'utf-8', f)
=> "\326\307\304\334360\323\357\322\364\326\372\300\355.txt"
1.8.7 :006 > URI.escape f
=> "%C3%96%C3%87%C3%84%C3%9C360%C3%93%C3%AF%C3%92%C3%B4%C3%96%C3%BA%C3%80%C3%AD.txt"
1.8.7 :007 > URI.escape g
=> "%D6%C7%C4%DC360%D3%EF%D2%F4%D6%FA%C0%ED.txt"
一般に、特定のエンコーディングを使用しているサーバーに依存することはできないことに注意してください。utf-8を使用する必要がありますが、この場合は明らかにそうではありません。