使用shrine和aws-sdk上传到digitalocean空间时出错

时间:2018-02-06 10:25:42

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

我正在使用神社直接上传到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以允许所有请求,如下面的

Cors settings

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

<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的错误。但是,如果是这样的话我该如何补充呢?

2 个答案:

答案 0 :(得分:2)

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

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)

答案 1 :(得分:0)

我发现解决方案是手动添加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),
}

我不知道这是最好的方法,因为它将根据contentType自动设置mime type,并在上传到亚马逊s3时正常工作。但不知怎的,这与digitalocean无效。因此我们必须手动指定这样才能使用空格。