TL;DR
It Would Be Nice If™ if DirectUpload
accepted a key argument to customize and override the default hash-based blob naming and to support sub-dirs within buckets.
(Others have asked for this before, e.g. in this thread that began in 2022))
Proposal
The Edge Rails docs illustrate how ActiveStorage::Attached::Many#attach
accepts an optional :key
argument to name and organize blobs (section 3.3 Attaching File/IO Objects). As the docs describe,
AWS S3 otherwise uses a random key to name your files. [Specifying a key] is helpful if you want to organize your S3 Bucket files better.
I this feature of ActiveStorage in Rails — in my experience, legible filenames + directory structures can be quite helpful in debugging or troubleshooting scenarios. An opaque tree of checksum hashes feels a little more fragile to me personally.
But for DirectUpload, I wasn’t able to find docs in support of equivalent customization options for JS use cases (e.g. from a Vue or Svelte or React app with a Rails back-end). Does the JS DirectUpload
api support passing a custom key function the way the Rails one does?
Context
Mapping files to specific ActiveStorage sub-directories and/or specific file/blob naming schemas is supported and can be helpful eg. for some use cases, it may be valuable to preserve the filename, or to organize by date, or whatever.
For example, the following s3 key method:
- preserves the original input filename
- adds a statistically unique-ish suffix (not saying it’s great code, just an example)
- organizes files into two-digit year / two-digit month directories for archival purposes (and easier reverse-engineering in the case of a debugging scenario):
def attach_image(img_path)
images.attach(
io: File.open(img_path),
filename: File.basename(img_path),
key: image_storage_key(img_path)
)
end
private
def image_storage_key(img_path)
filename = File.basename(img_path, ".*")
ext = img_path.match( %r{\w{3,4}$} )
t = Date.today
month_year = t.year.to_s.slice(2,2) + "%02d" % t.month
"#{month_year}-#{filename}-#{SecureRandom.hex.slice(0,6)}.#{ext}"
end
System configuration
Rails version: 7.2.2