【问题标题】:error on uploading to digitalocean spaces using shrine and aws-sdk使用神社和 aws-sdk 上传到 digitalocean 空间时出错
【发布时间】:2018-07-16 09:06:28
【问题描述】:

我正在使用神社直接上传到aws-s3 存储桶并且工作正常。现在我想改用 DigitalOcean spaces。所以我改变了一些神殿的设置,如下所示(只改变了与空格相关的env变量)。

require "shrine"
require "shrine/storage/s3"

s3_options = {
    access_key_id: ENV["SPACES_ACCESS_KEY_ID"],
    secret_access_key: ENV["SPACES_SECRET_ACCESS_KEY"],
    region: ENV["SPACES_REGION"],
    bucket: ENV["SPACES_BUCKET"],
    endpoint: ENV["SPACES_ENDPOINT"]
}

Shrine.storages = {
    cache: Shrine::Storage::S3.new(prefix: "cache", upload_options: {acl: "public-read"}, **s3_options),
    store: Shrine::Storage::S3.new(prefix: "store", upload_options: {acl: "public-read"}, **s3_options),
}

Shrine.plugin :activerecord
Shrine.plugin :presign_endpoint
Shrine.plugin :restore_cached_data
Shrine.plugin :backgrounding

Shrine::Attacher.promote {|data| UploadJob.perform_async(data)}
Shrine::Attacher.delete {|data| DeleteJob.perform_async(data)}

我还在空格中​​添加了 cors 以允许所有请求,如下所示

但是当我上传时,我收到了这个错误。

<Error><Code>AccessDenied</Code><Message>Policy missing condition: Content-Type</Message><BucketName>testing-dev</BucketName><RequestId>tx0000000036366363370-3663t37373-33883-sgp1a</RequestId><HostId>349494-sgp1a-sgp</HostId></Error>

这可能是什么问题?我可以看到策略中缺少告诉content-type 的错误。但是如果是这样,我该如何添加呢?

【问题讨论】:

    标签: ruby-on-rails aws-sdk digital-ocean shrine


    【解决方案1】:

    我发现解决办法是手动添加contentType

    所以我就这样更新了

    Shrine.storages = {
        cache: Shrine::Storage::S3.new(prefix: "cache", upload_options: {acl: "public-read", content_type: "png/jpeg"}, **s3_options),
        store: Shrine::Storage::S3.new(prefix: "store", upload_options: {acl: "public-read", content_type: "png/jpeg"}, **s3_options),
    }
    

    我不知道这是根据神社文档的最佳方法,它将根据mime type 自动设置contentType,并且在上传到亚马逊s3 时会正常工作。但不知何故,这不适用于digitalocean。所以我们必须像这样手动指定以使其与空格一起使用。

    【讨论】:

    • 这是可行的,因为来自:upload_options 的选项在生成预签名时也会传入。但是,正如您所说,这会使内容类型硬编码,而不是实际反映上传文件的 MIME 类型。我提供了一个替代解决方案。
    • @janko-m 谢谢你说清楚。如此伟大的宝石。 :)
    【解决方案2】:

    似乎 DigitalOcean Spaces 现在要求 presign 策略包含contentType 条件。 presign 策略是在 presign 端点中生成的,因此您可以根据 filename 查询参数告诉它添加 :content_type

    Shrine.plugin :presign_endpoint, presign_options: -> (request) do
      filename     = request.params["filename"]
      extension    = File.extname(filename)
      content_type = Rack::Mime.mime_type(extension)
    
      { content_type: content_type }
    end
    

    这应该使:content_type 始终存在,因为如果filename 没有扩展名或扩展名无法识别,Rack::Mime.mime_type 将返回application/octet-stream,这是 S3 默认分配给对象的内容类型。

    只需确保您在发送预签名请求时在客户端传递了filename 查询参数。例如。使用window.fetch 会是:

    fetch('/presign?filename=' + file.name)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-23
      • 2019-04-03
      • 2020-05-07
      • 1970-01-01
      • 1970-01-01
      • 2017-10-17
      • 2016-01-21
      • 1970-01-01
      相关资源
      最近更新 更多