Ответ 1
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)
UPDATE: см. комментарий ниже Строка кодировки URL-адреса Ruby
Как я 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 '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)
UPDATE: см. комментарий ниже Строка кодировки URL-адреса Ruby
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-urlencoded
, которая требует, чтобы пробелы были экранированы до +
, тогда как 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"
Я создал жемчужину, чтобы сделать чистую кодировку 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).
Я изначально пытался избежать специальных символов только в имени файла (не на пути) из полной строки 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"
Основываясь на 2 ответах разных SO question, похоже, что 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"