Ruby url编码字符串

HRÓ*_*LFR 131 ruby string uri ruby-on-rails urlencode

我如何URI ::编码一个字符串,如:

\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a
Run Code Online (Sandbox Code Playgroud)

要获得如下格式:

%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A
Run Code Online (Sandbox Code Playgroud)

(根据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>'
Run Code Online (Sandbox Code Playgroud)

也,

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>'
Run Code Online (Sandbox Code Playgroud)

我看了很多关于互联网的事情并没有找到(或者更可能错过)一种方法来做到这一点,虽然我几乎肯定我前几天毫无困难地做了这件事.

谢谢!

kai*_*ain 173

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)
Run Code Online (Sandbox Code Playgroud)

更新:请参阅Ruby url编码字符串下面的注释

  • 他们弃用了那个方法,改用*`CGI.escape`*. - > [http://www.ruby-forum.com/topic/207489#903709 ](http://www.ruby-forum.com/topic/207489#903709).您还应该能够使用`URI.www_form_encode`*`URI.www_form_encode_component`*,但我从未使用过那些 (62认同)
  • `force_encoding('binary')`可能是一个更自我记录的选择. (2认同)
  • 这里不需要'require'open-uri'.你的意思是'要求'uri'`? (2认同)

Jar*_*eck 70

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"
Run Code Online (Sandbox Code Playgroud)

取自@ J-Rou的评论


Jen*_*ave 70

如今,你应该使用ERB::Util.url_encodeCGI.escape.它们之间的主要区别在于它们对空间的处理:

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

>> CGI.escape("foo/bar? baz&")
=> "foo%2Fbar%3F+baz%26"
Run Code Online (Sandbox Code Playgroud)

CGI.escape遵循CGI/HTML表单规范,并为您提供一个application/x-www-form-urlencoded字符串,它需要转义空格+,而ERB::Util.url_encode遵循RFC 3986,它要求将它们编码为%20.

有关更多讨论,请参阅此答案.


kan*_*kyu 9

我最初只是试图从完整的 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"
Run Code Online (Sandbox Code Playgroud)

基于“为什么 URI.escape() 被标记为过时以及这个 REGEXP::UNSAFE 常量在哪里? ”中的两个答案,它看起来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"
Run Code Online (Sandbox Code Playgroud)


Ale*_*ein 8

你可以使用Addressable::URIgem:

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" 
Run Code Online (Sandbox Code Playgroud)

它使用更现代的格式,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" 
Run Code Online (Sandbox Code Playgroud)


Thi*_*cao 8

代码:

str = "http://localhost/with spaces and spaces"
encoded = URI::encode(str)
puts encoded
Run Code Online (Sandbox Code Playgroud)

结果:

http://localhost/with%20spaces%20and%20spaces
Run Code Online (Sandbox Code Playgroud)


foo*_*mip 5

我创建了一个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"
Run Code Online (Sandbox Code Playgroud)

它将uri转换功能添加到String类中.您也可以使用您想要使用的可选编码字符串传递一个参数(如果直接UTF-8编码失败,默认设置为编码'binary').