LoginSignup
3
2

More than 1 year has passed since last update.

S3に保存した画像をRailsで取得する

Last updated at Posted at 2022-06-26

結論

s3_resource = Aws::S3::Resource.new(xxx)
s3_resource.bucket('BUCKET_NAME').object(KEY_NAME).get.body.read

背景

S3にアップロードしてある画像データを、RailsのViewで動的に表示したかった。

調べたこと

  1. S3に画像がどう格納されているか
  2. そもそもの画像データ

S3にどう画像が格納されているか

Amazon S3 は、一意のキー値を使用して、必要な数のオブジェクトを保存できるオブジェクトストアです。これらのオブジェクトは 1 つ以上のバケットに保存し、各オブジェクトのサイズは最大 5 TB です。

つまり、S3にアップロードしている画像やテキストデータ = オブジェクト
オブジェクトにアクセスできるのがキー
オブジェクトを保管しているのがバケット

s3.rb
## バケットのリスト取得
s3_resource.buckets
=> #<Aws::S3::Bucket::Collection:0x0000ffff584ea680
 @batches=#<Enumerator: ...>,
 @limit=nil,
 @size=nil>

## バケット単体取得
s3_resource.buckets.first
=> #<Aws::S3::Bucket:0x0000ffff542af388
 @arn=nil,
 @client=#<Aws::S3::Client>,
 @data=#<struct Aws::S3::Types::Bucket name="test_bucket", creation_date=2022-06-24 14:23:15.155 UTC>,
 @name="test_bucket", #  <-- bucket名 -->
 @resolved_region="us-east-1",
 @waiter_block_warned=false>

## バケット名を指定する
s3_resource.bucket("test_bucket")
#<Aws::S3::Bucket:0x0000ffff61881240
 @arn=nil,
 @client=#<Aws::S3::Client>,
 @data=#<struct Aws::S3::Types::Bucket name="test_bucket", creation_date=2022-06-24 14:23:15.155 UTC>,
 @name="test_bucket", #  <-- bucket名 -->
 @resolved_region="us-east-1",
 @waiter_block_warned=false>

## バケット名を指定してオブジェクトのリスト取得する
s3_resource.bucket("test_bucket").objects
=> #<Aws::S3::ObjectSummary::Collection:0x0000ffff5c03cda0
 @batches=#<Enumerator: ...>,
 @limit=nil,
 @size=nil>

## バケット名とオブジェクトのキーを指定してオブジェクトを取得する
s3_resource.bucket("test_bucket").object("1")
=> #<Aws::S3::Object:0x0000ffff5c145738
 @bucket_name="test_bucket",
 @client=#<Aws::S3::Client>,
 @data=nil,
 @key="1",
 @waiter_block_warned=false>

ここまでで、オブジェクトにたどり着くことができましたが、画像ってどう取ればいいんだ?
という謎になり、画像について調べます。

そもそもの画像データ

バイナリデータ(binary data)とは、コンピュータが理解しやすいデータ(2進数で表現されたデータ)
バイナリデータは、画像ファイルや音声ファイル、動画ファイル、圧縮ファイルなど、コンピュータが扱えるファイルは、すべてバイナリデータです。

つまり、S3のオブジェクトからバイナリデータを取得すれば良いということがわかりました。

ここで、Aws::S3::Objectのドキュメントから、オブジェクトの読み込みのメソッドのgetを発見します。

s3.rb
s3_resource.bucket("test_bucket").object("1").get
=> #<struct Aws::S3::Types::GetObjectOutput
 body=#<StringIO:0x0000ffff5c011ab0>,
 delete_marker=nil,
 accept_ranges="bytes",
 expiration=nil,
 restore=nil,
 last_modified=2022-06-24 14:23:15 +0000,
 content_length=24972,
 etag="\"e4b088734dace101b4302a729f22cd70\"",
 checksum_crc32=nil,
 checksum_crc32c=nil,
 checksum_sha1=nil,
 checksum_sha256=nil,
 missing_meta=nil,
 version_id=nil,
 cache_control=nil,
 content_disposition=nil,
 content_encoding=nil,
 content_language=nil,
 content_range=nil,
 content_type="binary/octet-stream",
 expires=nil,
 expires_string=nil,
 website_redirect_location=nil,
 server_side_encryption=nil,
 metadata={},
 sse_customer_algorithm=nil,
 sse_customer_key_md5=nil,
 ssekms_key_id=nil,
 bucket_key_enabled=nil,
 storage_class=nil,
 request_charged=nil,
 replication_status=nil,
 parts_count=nil,
 tag_count=nil,
 object_lock_mode=nil,
 object_lock_retain_until_date=nil,
 object_lock_legal_hold_status=nil>

戻り値であるAws::S3::Types::GetObjectOutputbodyがStringIOの型だったので怪しいと思い、調べるとビンゴ。Object dataを返してくれるそうです。
https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Types/GetObjectOutput.html

s3.rb
s3_resource.bucket("test_bucket").object("1").get.body
=> #<StringIO:0x0000ffff60e958d0>

# StringIOを読み込む
s3_resource.bucket("test_bucket").object("1").get.body.read
=> "\xFF\xD8\xFF\xE0\u0000\u0010JFIF\u0000\u0001\xDB\u0000C\u0000\u0003\u0002\u0002\u0002\u0002\u0002\u0003\u0002\u0....

き、、きたーーー。2進数ではないけど見たことある画像データっぽいやつ!
これでS3から画像データを取得することができました。

わかったこと

  • S3から画像を取得するには Aws::S3::Types::GetObjectOutputを使うこと
  • 画像データはバイナリデータ
  • S3では画像などをオブジェクトという
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2