Ruby url编码string

我如何URI ::编码一个string,如:

\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a 

为了得到它的格式如下:

 %124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A 

(根据RFC 1738)

以下是我所尝试的:

 irb(main):123:0> URI::encode "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a" ArgumentError: invalid byte sequence in UTF-8 from /usr/local/lib/ruby/1.9.1/uri/common.rb:219:in `gsub' from /usr/local/lib/ruby/1.9.1/uri/common.rb:219:in `escape' from /usr/local/lib/ruby/1.9.1/uri/common.rb:505:in `escape' from (irb):123 from /usr/local/bin/irb:12:in `<main>' 

也,

 irb(main):126:0> CGI::escape "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a" ArgumentError: invalid byte sequence in UTF-8 from /usr/local/lib/ruby/1.9.1/cgi/util.rb:7:in `gsub' from /usr/local/lib/ruby/1.9.1/cgi/util.rb:7:in `escape' from (irb):126 from /usr/local/bin/irb:12:in `<main>' 

我已经看了所有关于互联网,并没有发现(或更可能错过)一个方法来做到这一点,虽然我几乎积极的,有一天,我没有任何麻烦,所有这一切。

谢谢!

 require 'open-uri' str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a".force_encoding('ASCII-8BIT') puts URI::encode(str) 

更新:请参阅Ruby url编码string下面的注释

 str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a" require 'cgi' CGI.escape(str) # => "%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A" 

来自@ J-Rou的评论

现在,你应该使用ERB::Util.url_encode或者CGI.escape 。 他们之间的主要区别是他们处理空间:

 >> ERB::Util.url_encode("foo/bar? baz&") => "foo%2Fbar%3F%20baz%26" >> CGI.escape("foo/bar? baz&") => "foo%2Fbar%3F+baz%26" 

CGI.escape遵循CGI / HTML格式规范,并为您提供一个application/x-www-form-urlencodedstring,该string需要将空格转义为+ ,而ERB::Util.url_encode遵循RFC 3986 ,这要求对其进行编码为%20

看到这个答案更多的讨论。

你可以使用Addressable::URI gem:

 require 'addressable/uri' string = '\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a' Addressable::URI.encode_component(string, Addressable::URI::CharacterClasses::QUERY) # "%5Cx12%5Cx34%5Cx56%5Cx78%5Cx9a%5Cxbc%5Cxde%5Cxf1%5Cx23%5Cx45%5Cx67%5Cx89%5Cxab%5Cxcd%5Cxef%5Cx12%5Cx34%5Cx56%5Cx78%5Cx9a" 

它比CGI.escape使用更现代的格式,例如,它将空间正确地编码为%20而不是+符号,您可以在维基百科文章中阅读更多内容

 2.1.2 :008 > CGI.escape('Hello, this is me') => "Hello%2C+this+is+me" 2.1.2 :009 > Addressable::URI.encode_component('Hello, this is me', Addressable::URI::CharacterClasses::QUERY) => "Hello,%20this%20is%20me" 

我创build了一个gem,使uri编码的东西在代码中更清洁。 它为您处理二进制编码(在上面的代码中添加了一些示例的东西)。

运行gem install uri-handler

 require 'uri-handler' str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a".to_uri # => "%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A" 

它将uri转换function添加到String类中。 你也可以传递一个参数给你想要使用的可选编码string(如果UTF-8编码失败,默认设置为编码“二进制”)。

我本来是试图从完整的urlstring只在文件名(不在path上)转义特殊字符。 ERB::Util.url_encode不适用于我的使用。

 helper.send(:url_encode, "http://example.com/?a=\11\15") # => "http%3A%2F%2Fexample.com%2F%3Fa%3D%09%0D" 

基于不同SO 问题的 2个答案,看起来像URI::RFC2396_Parser#escape比使用URI::Escape#escape更好。 但是,他们对我来说都是一样的。

 URI.escape("http://example.com/?a=\11\15") # => "http://example.com/?a=%09%0D" URI::Parser.new.escape("http://example.com/?a=\11\15") # => "http://example.com/?a=%09%0D"