I am having an issue when uploading to Cloudflare R2 object storage. I tried using S3, which works well, but I need to set up R2. For uploading I am using gem Shrine.
I created a “demo code” that returns the same error.
The files are successfully uploaded to the cache, but the process fails when moving them out of it. I have attached a screenshot showing that the files are correctly stored in the cache.
<code>require "bundler/setup"
require "active_record"
require "shrine"
require "shrine/storage/file_system"
require "shrine/storage/s3"
require "down"
s3_options = {
bucket: "bucket_name",
region: "auto",
access_key_id: "access_key_id",
secret_access_key: "secret_access_key",
endpoint: "https://r2.endpoint.domain",
force_path_style: true,
public: false
}
Shrine.storages = {
cache: Shrine::Storage::S3.new(prefix: "cache", upload_options: {}, **s3_options),
store: Shrine::Storage::S3.new(copy_options: {}, **s3_options)
}
Shrine.plugin :activerecord
Shrine.plugin :pretty_location
class ImageUploader < Shrine
def generate_location(io, record: nil, **context)
tenant_id = record[:tenant_id] || "default"
"tenants/#{tenant_id}/#{super}"
end
end
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.connection.create_table(:posts) { |t| t.text :image_data }
class Post < ActiveRecord::Base
include ImageUploader::Attachment(:image)
end
post = Post.create(image: Down.download("https://images.pexels.com/photos/15286/pexels-photo.jpg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"))
puts "Image uploaded successfully with data: #{post.image_data}"
</code>
<code>require "bundler/setup"
require "active_record"
require "shrine"
require "shrine/storage/file_system"
require "shrine/storage/s3"
require "down"
s3_options = {
bucket: "bucket_name",
region: "auto",
access_key_id: "access_key_id",
secret_access_key: "secret_access_key",
endpoint: "https://r2.endpoint.domain",
force_path_style: true,
public: false
}
Shrine.storages = {
cache: Shrine::Storage::S3.new(prefix: "cache", upload_options: {}, **s3_options),
store: Shrine::Storage::S3.new(copy_options: {}, **s3_options)
}
Shrine.plugin :activerecord
Shrine.plugin :pretty_location
class ImageUploader < Shrine
def generate_location(io, record: nil, **context)
tenant_id = record[:tenant_id] || "default"
"tenants/#{tenant_id}/#{super}"
end
end
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.connection.create_table(:posts) { |t| t.text :image_data }
class Post < ActiveRecord::Base
include ImageUploader::Attachment(:image)
end
post = Post.create(image: Down.download("https://images.pexels.com/photos/15286/pexels-photo.jpg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"))
puts "Image uploaded successfully with data: #{post.image_data}"
</code>
require "bundler/setup"
require "active_record"
require "shrine"
require "shrine/storage/file_system"
require "shrine/storage/s3"
require "down"
s3_options = {
bucket: "bucket_name",
region: "auto",
access_key_id: "access_key_id",
secret_access_key: "secret_access_key",
endpoint: "https://r2.endpoint.domain",
force_path_style: true,
public: false
}
Shrine.storages = {
cache: Shrine::Storage::S3.new(prefix: "cache", upload_options: {}, **s3_options),
store: Shrine::Storage::S3.new(copy_options: {}, **s3_options)
}
Shrine.plugin :activerecord
Shrine.plugin :pretty_location
class ImageUploader < Shrine
def generate_location(io, record: nil, **context)
tenant_id = record[:tenant_id] || "default"
"tenants/#{tenant_id}/#{super}"
end
end
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.connection.create_table(:posts) { |t| t.text :image_data }
class Post < ActiveRecord::Base
include ImageUploader::Attachment(:image)
end
post = Post.create(image: Down.download("https://images.pexels.com/photos/15286/pexels-photo.jpg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"))
puts "Image uploaded successfully with data: #{post.image_data}"
Gemfile:
<code>source "https://rubygems.org"
gem "bundler", "~> 2.0"
gem "activerecord", "~> 7.1.3.4"
gem "shrine", "~> 3.6.0"
gem 'aws-sdk-s3', '~> 1.159.0'
gem "down"
gem 'image_processing', '~> 1.13'
gem 'mini_exiftool', '~> 2.11.0'
gem "sqlite3", "~> 1.4"
gem 'nokogiri'
</code>
<code>source "https://rubygems.org"
gem "bundler", "~> 2.0"
gem "activerecord", "~> 7.1.3.4"
gem "shrine", "~> 3.6.0"
gem 'aws-sdk-s3', '~> 1.159.0'
gem "down"
gem 'image_processing', '~> 1.13'
gem 'mini_exiftool', '~> 2.11.0'
gem "sqlite3", "~> 1.4"
gem 'nokogiri'
</code>
source "https://rubygems.org"
gem "bundler", "~> 2.0"
gem "activerecord", "~> 7.1.3.4"
gem "shrine", "~> 3.6.0"
gem 'aws-sdk-s3', '~> 1.159.0'
gem "down"
gem 'image_processing', '~> 1.13'
gem 'mini_exiftool', '~> 2.11.0'
gem "sqlite3", "~> 1.4"
gem 'nokogiri'
PS: In actual use, I am using Ruby on Rails 7.1
For any help I will be very happy.
Cloudflare R2 – uploaded screenshot
Console error
2