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

时间:2012-05-10 20:36:30

标签: ruby ruby-on-rails-3 jruby url-encoding

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

www.domain.com/.../ÖÇÄÜ360ÓïÒôÖúÀí.txt

尝试下载上述网址时,会失败。使用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

但是,如果我按照URL Encoding Reference进行操作,则可以:

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”

1 个答案:

答案 0 :(得分:15)

哦,角色编码的乐趣!

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

然而,接收服务器正在解释这些字节(在从%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,但显然不是这种情况。

相关问题