フロントから直でS3にアップロードしたい時に署名付きのURLを発行すると思うが、それを行うための mutation を書いた。
バージョン情報
Ruby: 2.6.3
graphql-ruby: 1.10.1
aws-sdk-s3 1.67.1
# frozen_string_literal: true
require 'aws-sdk-s3'
module Mutations
class CreateS3PresignedUrlMutation < Mutations::BaseMutation
description 'S3アップロードのための署名付きURLの発行'
argument :filename, String, required: true
field :presigned_url, String, null: true
field :presigned_fields, GraphQL::Types::JSON, null: true
field :errors, [Types::ObjectTypes::GraphqlError], null: false
def resolve(filename:)
credentials = Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'])
s3_resource = Aws::S3::Resource.new(region: ENV['S3_REGION'], credentials: credentials)
s3_bucket = s3_resource.bucket(ENV['S3_BUCKET_NAME'])
# 仮に同じfilenameでも被らんように uuid を発行している。ユースケースに応じて他のID使うなりするといい
key = "uploads/#{SecureRandom.uuid}/#{filename}"
presigned_object = s3_bucket.presigned_post(key: key, acl: 'public-read', success_action_status: '201')
if presigned_object
{
presigned_url: presigned_object.url,
# ここで `no implicit conversion of nil into String` が起きる方は aws-sdk-s3 のバージョンが低い可能性があります
# https://github.com/aws/aws-sdk-ruby/issues/1071#issuecomment-173994607
presigned_fields: presigned_object.fields,
errors: []
}
else
# エラーレスポンスを返す
end
end
end
end