【问题标题】:Use Fog with Ruby to generate a Pre-signed URL to PUT a file in Amazon S3使用 Fog 和 Ruby 生成预签名 URL 以将文件放入 Amazon S3
【发布时间】:2014-01-30 15:52:15
【问题描述】:

我正在使用 Fog gem 来生成预签名的 url。我可以成功地做到这一点来获得对文件的读取权限。这是我的工作:

    fog_s3 = Fog::Storage.new({
          :provider                 => 'AWS',
          :aws_access_key_id        => key,
          :aws_secret_access_key    => secret
    })
    object_path = 'foo.wav' 
    expiry = Date.new(2014,2,1).to_time.to_i
    url = fog_s3.directories.new(:key => bucket).files.new(:key => object_path).url(expiry,path_style: true)

但是当我尝试上传文件时这不起作用。有没有办法指定 http 动词,使其成为 PUT 而不是 GET?

EDIT 我看到了一个方法:put_object_url,它可能会有所帮助。我不知道如何访问它。

谢谢

编辑根据您的建议:

它有帮助 - 它给了我一个 PUT - 而不是 GET。但是,我仍然遇到问题。我添加了内容类型:

    headers = { "Content-Type" => "audio/wav" }
    options = { path_style: true }
    object_path = 'foo.wav' 
    expiry = Date.new(2014,2,1).to_time.to_i  
    url = fog_s3.put_object_url(bucket,object_path, expiry, headers, options)

但网址中不包含Content-Type。当从 HTML 中的 Javascript 完成时,我在 url 中得到 Content-Type,这似乎有效。这是雾的问题吗?还是我的标题不正确?

【问题讨论】:

    标签: ruby amazon-s3 storage fog pre-signed-url


    【解决方案1】:

    我认为 put_object_url 确实是您想要的。如果您按照 url 方法返回到它的定义位置,您可以看到它使用了一个类似的方法,称为 get_object_url here (https://github.com/fog/fog/blob/dc7c5e285a1a252031d3d1570cbf2289f7137ed0/lib/fog/aws/models/storage/files.rb#L83)。您应该能够做类似的事情,并且可以通过从上面已经创建的fog_s3 对象调用此方法来实现。它最终应该看起来像这样:

    headers = {}
    options = { path_style: true }
    url = fog_s3.put_object_url(bucket, object_path, expires, headers, options)
    

    请注意,与 get_object_url 不同的是,其中隐藏了一个额外的 headers 选项(我相信您可以使用它来执行 set Content-Type 之类的操作)。

    希望对您有所帮助,但如果您还有其他问题,请告诉我。谢谢!

    附录

    嗯,毕竟可能存在与此相关的错误(我现在想知道这部分代码已经执行了多少)。我认为你应该能够解决它(但我不确定)。我怀疑您也可以将选项中的值复制为查询参数。可以试试这样的吗?

    headers = query = { 'Content-Type' => 'audio/wav' }
    options = { path_style: true, query: query }
    url = fog_s3.put_object_url(bucket, object_path, expires, headers, options)
    

    希望这可以为您填补空白(如果是这样,我们可以考虑更多关于在雾中修复该行为,如果这样做有意义的话)。谢谢!

    【讨论】:

    • 可能是一个错误,老实说,不知道这段代码执行了多少/多好(对此感到抱歉)。我会用更多信息/想法更新我的答案。
    • geemus - 你是个天才!附录起到了作用。我需要知道如何在其中添加标题。如果您认为这是一个错误,我们可以创建一个问题(甚至是文档问题)来帮助他人?
    • 我认为这可能是一个错误,虽然我不完全确定我想如何修复它(这有点尴尬,因为在多个地方重用了一些代码)。但第一步肯定是个问题。如果您可以创建一个包含其中一些细节的东西,那就太好了(我们可以在那里讨论并解决问题)。谢谢!
    • @geemus 你是个该死的巫师!我一直在努力让这个工作好几个小时。我阅读了无数关于此事的亚马逊文章和博客文章,但没有任何效果。我心想,“也许 Fog 已经做到了?”找到put_object_url 并最终找到了解决这个问题的方法。我可以验证上述方法是否适用于从浏览器使用 CORS 为 PUT 上传生成签名 URL。谢谢!
    【解决方案2】:

    我建议您尝试使用 bucket.files.create 操作,而不是使用 *put_object_url*,它采用 Fog 文件哈希属性并返回 Fog::Storage:: AWS::文件

    我更喜欢把它分解成更多的步骤,这里是一个例子:

    fog_s3 = Fog::Storage.new({
       :provider                 => 'AWS',
       :aws_access_key_id        => key,
       :aws_secret_access_key    => secret
    })
    
    # Define the filename
    ext = :wav
    filename = "foo.#{ext.to_s}"
    
    # Path to your audio file?
    path ="/"
    
    # Define your expiry in the amount of seconds
    expiry = 1.day.to_i
    
    #Initialize the bucket to store too
    fog_bucket = connection.directories.get(bucket)
    
    file = {
       :key => "#{filename}",
       :body => IO.read("#{path}#{filename}"),
       :content_type => Mime::Type.lookup_by_extension(ext),
       :cache_control => "public, max-age=#{expiry}",
       :expires => CGI.rfc1123_date(Time.now + expiry),
       :public => true
    }
    
    # Returns a Fog::Storage::AWS::File
    file = fog_bucket.files.create( file )
    
    # Now to retrieve the public_url
    url = file.public_url
    

    注意:对于子目录的结帐,AWS 存储桶的 :prefix 选项。

    雾文件文档: 可选属性...页面底部,:) http://rubydoc.info/gems/fog/Fog/Storage/AWS/File

    希望该示例将有助于解释创建雾文件的步骤...干杯! :)

    【讨论】:

    • 嗨,Kevin,如果我的服务器上有本地文件,该示例运行良好。但是,我需要生成 URL 并将其交给基于浏览器的客户端应用程序。然后,客户端应用程序使用此 URL 上传文件。我的服务器不充当 AWS 的代理,而是帮助控制对私有存储桶的访问。感谢您的建议,因为我可以在应用程序的另一部分使用它。 :-)
    猜你喜欢
    • 2010-09-10
    • 2016-06-17
    • 2018-12-27
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    相关资源
    最近更新 更多