如何在 Rails 中使用空格作为 '%20' 而不是 '+' 获取 url 的参数

How to get params for url with whitespace as '%20' instead of '+' in Rails

如果我有这个参数可以添加到 URL

params = { name: 'John Key' }

并使用方法 to_param:

params.to_param
 => "name=John+Key"

重点是“+”未被使用的服务正确读取,需要“%20”而不是 name=John%20KeyWhen to encode space to plus (+) or %20?

有没有办法在不使用 gsub 的情况下 return 带有“%20”的参数?

您尝试过使用 uri 吗?例如

require 'uri' URI.escape('John Smith')

本例中的结果应该是John%20Smith

从其他 post 那里了解到 URI.escape 在技术上已被弃用。其中 h 代表散列,而 k 是散列中的键,试试这个:

params.keys.inject({}) {|h, k| h[k] = ERB::Util.url_encode(params[k]); h }

我建议只坚持使用 gsub,或许可以用注释来解释这种行为的必要性。

虽然您 可以 使用 URI.escape 解决问题,但据说它已被弃用,因为它不完全符合 RFC 规范。 See here 写了一篇很棒的文章。

Hash#to_paramHash#to_query的别名,调用Object#to_query。演示此 +%20 问题的最简单示例是:

'John Key'.to_query(:name) # => "name=John+Key"

Object#to_query的实现是:

def to_query(key)
  "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
end

因此,我们发现:

CGI.escape("John Key") # => "John+Key"

因此,这就是为什么我引用了 CGI.escapeURI.escape 之间的区别。

怎么样

URI.encode 'John Smith'
# => John%20Smith

不是真的。

建议使用:your_params_hash.to_query.gsub("+", "%20")

扩展 Julie 的答案以实现编码值字符串而不是散列。

随着 URI.encode 的贬值,可以使用 ERB::Util.url_encode 实现这一点,但是您只需要对键和值对进行编码,而不是对完整参数进行编码,然后将它们连接在一起。


params = { name: 'John Key' }

# not what we want
ERB::Util.url_encode(params) # => "%7B%3Aname%3D%3E%22John%20Key%22%7D"

这是一个(相当长的)命令,可以工作:

# Construct a new object (a string here) and build our params into it correctly.
# k = key of hash. 
# v = value of hash. 
# a = array created in each_with_object.

params.each_with_object([]) { |(k, v), a| a << [ERB::Util.url_encode(k), ERB::Util.url_encode(v)].join('=') }.join('&')

# => "name=John%20Key"

更多参数:

params = { name: 'John Key', occupation: 'Web Developer!', 'Bad Key' => 'but works' }

params.each_with_object([]) { |(k, v), a| a << [ERB::Util.url_encode(k), ERB::Util.url_encode(v)].join('=') }.join('&')

# => "name=John%20Key&occupation=Web%20Developer%21&Bad%20Key=but%20works"

相比于Hash.to_query

params.to_query

# => "Bad+Key=but+works&name=John+Key&occupation=Web+Developer%21"

如果你想要一个没有上下文的字符串的文字百分比编码(例如 RFC 5987 encoding of something like a Content-Disposition HTTP header's filename*=... value) then use of URI.escape / URI.encode (its alias) would have been correct. The core library documentation's suggested replacements 在这种情况下是错误的,因为它们不等价:

  • 转换为+,而不是%20
  • + 转换为 %2B,而不是 +

一些关于此的帖子建议 gsub 将字符串改回原始字符串,但这要简单得多:

...切换源代码以查看其工作原理 - 它只是一个没有上下文的钝编码器。当您知道自己在做什么时,这 正是您有时想要的,所以希望它不会从标准库中删除或弃用。

如果我有时间,我打算向核心库文档提交一个补丁,其中列出了 三个(不是两个)可能的替代方案,并提供了有关何时使用的更多信息他们每个人。现在,从大量 Google 的点击率和大量 at-best 的误导性回答中可以清楚地看出,社区对现状感到非常困惑。