文件名中的特殊字符影响了aws-sdk ruby gem的url_for方法

5

我正在使用官方的AWS Ruby S3 gem,但在使用“url_for”方法时遇到了特殊字符(如逗号、撇号)的文件问题。我正在使用最新的Ruby aws-sdk gem,我的代码如下:

s3 = AWS::S3::new
bucket = s3.buckets[bucket]
object = bucket.objects[object_address]
object_url = object.url_for(:read, :expires => 60*60, :secure => true)

对象被正确找到,但是我从url_for获取的URL会给出HTTPError:404 Not Found错误。如果文件名没有逗号或撇号,则可以正常工作。有没有一种处理方法,而无需限制文件名呢?

你的URL是什么样子? - sarnold
我已经为了保护隐私替换了一些部分,但这就是要点。它以https开头... //mybucket.s3.amazonaws.com/mypathstuff/test%2Ctest.png?AWSAccessKeyId=MYACCESSKEY&Expires=1323005992&Signature=lettersandnumbers%2Bt2RtdCnBAA%3D - Joel Friedlaender
我替换的部分是“mybucket”,“mypathstuff”和“lettersandnumbers”。我尝试过对URL进行编码/解码,但没有任何好处。 - Joel Friedlaender
2个回答

2

最近我遇到了同样的问题。在提交之前,我无法修复文件名,因此我没有使用#url_for,而是编写了自己的编码器。虽然它不能完全在aws-sdk gem中工作,但这并不太困难,只是有些烦人。

这是我的解决方案:

def url_for_read(path, opts)
  expire_date = (Time.zone.now + opts[:expires]).to_i
  request_string = "GET\n\n\n#{expire_date}\n/#{config[:bucket]}/#{path}"
  hmac = OpenSSL::HMAC.digest(digest, config[:secret_access_key], request_string)
  signature = URI.escape(Base64.encode64(hmac).strip)
  s3_url_domain + "#{path}?AWSAccessKeyId=#{config[:access_key_id]}&Expires=#{expire_date}&Signature=#{CGI::escape(signature)}"
end

这里假设您的aws信息存储在一个名为config的哈希表中,digest是一个'sha1',域名看起来像这样:https://<my_bucket>.s3-<region>.amazonaws.com。如果需要完整的类,您可以查看这个gist:https://gist.github.com/bunnymatic/9274108

在我的情况下,<StringToSign> 期望在内容类型后面有2个换行符(而不是3个)。AWS服务器的响应在这种情况下非常有帮助,此外,我还必须对文件名进行URL编码。 - Alfonso Embid-Desmet

2

您默认会转义URL字符串吗?例如:

object_url =  CGI.escape(object.url_for(:read, :expires => 60*60, :secure => true))

这将把字符串正确转义为浏览器可读格式。我对所有安全的S3 URL都这样做,因为签名中有时会有/+字符,如果没有正确转义,链接也会失败。这也会正确转义逗号和撇号。


我已经尝试过转义和不转义,似乎并没有关系。 - Joel Friedlaender
url_for 方法是否抛出了异常(HTTPError),还是只有当你尝试点击链接时才会显示 404 页面? - iwasrobbed
当我点击链接时,我会得到404页面。 - Joel Friedlaender

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接