我如何URI ::编码一个字符串,如:
\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 '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 encoding 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 forms spec,并给你一个application/x-www-form-urlencoded
字符串,这需要空格逃逸到+
,而ERB::Util.url_encode
遵循RFC 3986,这要求他们编码为%20
。
有关更多讨论,请参阅this answer。
您可以使用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
而不是+
标志,你可以在wikipedia article阅读更多
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"
我创建了一个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转换功能添加到String类中。您也可以使用您想要使用的可选编码字符串传递一个参数(如果直接UTF-8编码失败,默认设置为编码'binary')。
我原本试图从完整的url字符串中仅在文件名上(不在路径上)转义特殊字符。 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 question的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"
如果你想“编码”一个完整的URL,而不必考虑手动将它分成不同的部分,我发现以下工作方式与我以前使用URI.encode
的方式相同:
URI.parse(my_url).to_s
码:
str = "http://localhost/with spaces and spaces"
encoded = URI::encode(str)
puts encoded
结果:
http://localhost/with%20spaces%20and%20spaces