Ruby 如何对ASCII字符进行URL编码?

Ruby 如何对ASCII字符进行URL编码?,ruby,ruby-on-rails-3,jruby,url-encoding,Ruby,Ruby On Rails 3,Jruby,Url Encoding,我正在使用Ruby提取一个文件的URL来下载它。文件名包含utf8个字符,例如: www.domain.com/.../ÖÇÄÜ360ÓïÒôÖúÀí.txt 尝试下载上述URL时失败。使用URI::escape生成的URI也不起作用: www.domain.com/.../%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 但如果我遵循以下原则,它会起作用: www.domain.c

我正在使用Ruby提取一个文件的URL来下载它。文件名包含utf8个字符,例如:

www.domain.com/.../ÖÇÄÜ360ÓïÒôÖúÀí.txt
尝试下载上述URL时失败。使用
URI::escape
生成的URI也不起作用:

www.domain.com/.../%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
但如果我遵循以下原则,它会起作用:

www.domain.com/.../%D6%C7%C4%DC360%D3%EF%D2%F4%D6%FA%C0%ED.txt
我试图在Ruby中搜索一个编码完全相同的函数,但找不到任何函数。在我尝试编写一个实现上面链接中的表的函数之前,我想问一下是否有人知道任何现有的库可以这样做。如果我决定这样做,我应该编码什么字符范围,显然,不是所有字符


我正在使用JRuby 1.6.2和RUBY_VERSION=>“1.8.7”

哦,字符编码的乐趣

这里发生的事情如下。Ruby在内部将您提取的字符串存储为一个字节序列,即文件名的utf-8编码。在其上调用
URI.escape
时,这些字节将以
%xy
格式进行转义,结果字符串(现在仅由ASCII范围内的字节组成)将用作url

然而,在本例中,接收服务器正在解释这些字节(在从
%xy
表单中删除它们之后),就好像它们采用了不同的编码,因此它产生的文件名与它拥有的任何内容都不匹配

这里有一个使用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"

请注意,一般来说,您不能依赖使用任何特定编码的服务器。它应该使用utf-8,但显然不是在这种情况下。

字节C3 96是utf-8编码的Ö。ASCII中表示的字符与单字节D6相同。因此,解决这个问题的一种方法是将UTF-8字符转换为ASCII,然后URI::escape。但是这对没有ASCII等价物的Unicode字符没有帮助。你试过了吗?@davidgorline:这不起作用。除了“360”和“.txt”之外,所有字符都以“?”结尾。上面的例子是一个真实的例子,如果你有任何想法,你可以在字符串“ÖÄÜ360ÓÒÖÖÀí.txt”上测试它们,并告诉我如何做。非常感谢你的帮助。这是你应该避免的。该编码表正在使用,您也不应该使用它,您应该使用UTF-8。如果您需要拉丁语-1,则必须将UTF-8单独转换为拉丁语-1。@muistooshort比这更糟-表格是。这非常有用。我不知道编码后需要URI.escape。
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"