Class: Dscf::Core::FileStorage::Client
- Inherits:
-
Object
- Object
- Dscf::Core::FileStorage::Client
- Defined in:
- app/services/dscf/core/file_storage/client.rb
Overview
Low-level S3 client for object storage (Garage / MinIO / any S3-compatible service). This is an internal class - other engines should NOT use this directly; go through FileStorage, Uploader, or the Attachable concern instead.
Configuration is read from the environment:
S3_ENDPOINT_URL - e.g. http://garage:3900 (required)
S3_BUCKET - bucket name (required)
S3_ACCESS_KEY_ID - access key (required)
S3_SECRET_ACCESS_KEY - secret key (required)
S3_REGION - region (optional, defaults to "garage")
File keys are flat UUIDs (no "/") so they stay valid for the
files/:file_key route constraint (/[^\/]+/).
Defined Under Namespace
Classes: ConfigurationError, DownloadError, UploadError
Constant Summary collapse
- DEFAULT_REGION =
"garage"- DEFAULT_CONTENT_TYPE =
"application/octet-stream"
Instance Method Summary collapse
-
#delete(file_key) ⇒ Boolean
Delete an object.
-
#download(file_key) ⇒ Hash
Download a file from object storage.
-
#exists?(file_key) ⇒ Boolean
Check if an object exists.
-
#initialize(app_name: nil, record_class: nil) ⇒ Client
constructor
A new instance of Client.
-
#upload(file, filename: nil) ⇒ Hash
Upload a file to object storage.
Constructor Details
#initialize(app_name: nil, record_class: nil) ⇒ Client
Returns a new instance of Client.
32 33 34 35 36 37 38 39 |
# File 'app/services/dscf/core/file_storage/client.rb', line 32 def initialize(app_name: nil, record_class: nil) @endpoint = ENV["S3_ENDPOINT_URL"].presence @bucket = ENV["S3_BUCKET"].presence @access_key_id = ENV["S3_ACCESS_KEY_ID"].presence @secret_access_key = ENV["S3_SECRET_ACCESS_KEY"].presence @region = ENV.fetch("S3_REGION", DEFAULT_REGION) validate_configuration! end |
Instance Method Details
#delete(file_key) ⇒ Boolean
Delete an object.
101 102 103 104 105 106 107 |
# File 'app/services/dscf/core/file_storage/client.rb', line 101 def delete(file_key) s3.delete_object(bucket: @bucket, key: file_key) true rescue StandardError => e Rails.logger.error("FileStorage::Client delete error: #{e.}") false end |
#download(file_key) ⇒ Hash
Download a file from object storage.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'app/services/dscf/core/file_storage/client.rb', line 72 def download(file_key) response = s3.get_object(bucket: @bucket, key: file_key) { data: response.body.read, filename: response.["filename"].presence || file_key, content_type: response.content_type.presence || DEFAULT_CONTENT_TYPE } rescue Aws::S3::Errors::NoSuchKey => e raise DownloadError, "File not found: #{file_key} (#{e.})" rescue Aws::Errors::ServiceError => e raise DownloadError, "Download failed: #{e.}" end |
#exists?(file_key) ⇒ Boolean
Check if an object exists.
89 90 91 92 93 94 95 96 |
# File 'app/services/dscf/core/file_storage/client.rb', line 89 def exists?(file_key) s3.head_object(bucket: @bucket, key: file_key) true rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::NoSuchKey false rescue StandardError false end |
#upload(file, filename: nil) ⇒ Hash
Upload a file to object storage.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'app/services/dscf/core/file_storage/client.rb', line 45 def upload(file, filename: nil) prepared = prepare_file(file, filename) file_key = generate_file_key(prepared[:filename]) io = prepared[:io] io.rewind if io.respond_to?(:rewind) s3.put_object( bucket: @bucket, key: file_key, body: io, content_type: prepared[:content_type] || DEFAULT_CONTENT_TYPE, metadata: {"filename" => prepared[:filename].to_s} ) { file_key: file_key, filename: prepared[:filename], size: prepared[:size], content_type: prepared[:content_type] } rescue Aws::Errors::ServiceError => e raise UploadError, "Upload failed: #{e.}" end |