shrine
shrine.cr
File attachment toolkit for Crystal applications. Inspired by Shrine for Ruby.
Installation
Add to your shard.yml:
dependencies:
shrine:
github: jetrockets/shrine.cr
Run shards install.
Core Concepts
Shrine separates file uploads into two parts:
- Storage - where files are saved (disk, S3, SQLite)
- Uploader - how files are processed and managed
Storage Backends
filesystem
Saves files to local disk. Best for development and small applications.
storage = Shrine::Storage::FileSystem.new(
"uploads", # Base directory
prefix: "images", # Optional subdirectory
clean: true # Remove empty folders
)
# Generated URLs: "/uploads/images/abc123.jpg"
S3
Amazon S3 or compatible services (DigitalOcean Spaces, MinIO). Best for production.
require "awscr-s3"
client = Awscr::S3::Client.new(
region: "us-east-1",
aws_access_key: ENV["AWS_KEY"],
aws_secret_key: ENV["AWS_SECRET"]
)
storage = Shrine::Storage::S3.new(
bucket: "my-bucket",
client: client,
public: true, # Make files publicly accessible
prefix: "photos" # Store in subfolder
)
# Generated URLs: "https://my-bucket.s3.amazonaws.com/photos/abc123.jpg"
SQLite
Stores files directly in SQLite database. Good for small apps and prototyping.
storage = Shrine::Storage::SQLite.new(
"files.db", # Database file
table: "uploads" # Optional custom table name
)
# Generated URLs: "sqlite://files.db/uploads/abc123.jpg"
Memory
In-memory storage. Useful for testing.
storage = Shrine::Storage::Memory.new
# Data is lost when process ends
Plugins
DetermineMimeType
Detects actual MIME type from file content, not just extension.
require "shrine/plugins/determine_mime_type"
Shrine.plugin(Shrine::Plugins::DetermineMimeType)
# Now uploaded files have accurate mime_type metadata
uploaded.mime_type # => "image/jpeg" (detected from content)
Analyzers:
- File - Uses system file command (most accurate)
- Mime - Uses file extension (fastest)
- ContentType - Uses browser-provided header (least accurate)
StoreDimensions
Extracts image dimensions and adds them to metadata.
require "fastimage"
require "shrine/plugins/store_dimensions"
Shrine.plugin(Shrine::Plugins::StoreDimensions)
# After upload:
uploaded.width # => 1920
uploaded.height # => 1080
uploaded.dimensions # => {1920, 1080}
Requires fastimage.cr.
Custom Uploaders
Create reusable uploaders with custom logic:
class ImageUploader < Shrine
# Custom file naming
def generate_location(io, metadata, **options)
ext = File.extname(metadata["filename"].to_s)
"images/#{Random::Secure.hex(8)}#{ext}"
end
# Automatic image processing
def process(io, **options)
# Generate thumbnail
# Validate dimensions
# Strip metadata
io
end
end
# Usage
uploader = ImageUploader.new
uploaded = uploader.upload(file, "store")
documentation
License
MIT
Repository
shrine
Owner
Statistic
- 0
- 0
- 0
- 0
- 7
- about 1 month ago
- March 10, 2026
License
MIT License
Links
Synced at
Wed, 11 Mar 2026 03:03:17 GMT
Languages