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

标签 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

但如果我遵循 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"

最佳答案

哦,字符编码的乐趣!

这里发生的事情如下。 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,但在这种情况下显然不是。

关于ruby - 如何对 ASCII 字符进行 URL 编码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10541757/

相关文章:

java - JRuby warbler "compiled"命令在 Tomcat 中产生 ClassCastException

ruby-on-rails - Rails 3 with Devise for Authentication - 如何手动创建用户?

ruby-on-rails - 如何解决 Heroku 上未初始化常量 Rake::DSL 问题?

ruby-on-rails - rails 3 缓存 : expire action for named route

jar - 将 jruby on rails 应用程序编译为 jar?

java - 如何确定在 Linux 上使用 Java 还是 JRuby 是否正在运行不同的进程 ID?

ruby - 如何在 Ruby 中像这样设置哈希实例的值?

ruby - 使用 Nokogiri::XML::Builder 添加元素

iphone - 如何设置 UISlider Minimum Track Image 使其不会拉伸(stretch)?

ruby-on-rails - 如何处理 Rails 资源路由中的点字符?