ExOss is a unified S3-compatible and Alibaba Cloud OSS object storage library with multi-CDN support.
Overview
ExOss supports:
- Storage: Native Alibaba Cloud OSS and any S3-compatible service — AWS S3, Qiniu S3, MinIO, DigitalOcean Spaces, Cloudflare R2, etc.
- CDN: CloudFront, Qiniu CDN, Aliyun CDN, and any custom CDN via
ExOss.CDN.Behaviour - File transfer: Upload from local file, content, remote URL, or cloud-to-cloud copy
- Presigned URLs: Temporary upload/download URLs without exposing credentials
Installation
Add ex_oss to your mix.exs:
def deps do
[
{:ex_oss, "~> 1.2"}
]
endExOss automatically includes req for HTTP requests, ex_aws_s3 for S3
operations, and sweet_xml for parsing multipart upload responses. You do
not need to add these dependencies separately. See File Transfer
for details on local file uploads.
Quick Start
1. Define a Storage Module
defmodule MyApp.Storage do
use ExOss, otp_app: :my_app
end2. Configure
# config/config.exs
config :my_app, MyApp.Storage,
provider: :aws,
access_key_id: "AKIAIOSFODNN7EXAMPLE",
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
region: "us-east-1"3. Use
# Generate a presigned download URL (valid for 1 hour)
MyApp.Storage.authorize_download_url("bucket", "photos/cat.jpg", 3600)
# Generate upload credentials for direct-to-S3 upload
credential = MyApp.Storage.upload_credential("bucket", "photos/cat.jpg", 3600)
Req.put!(credential.presigned_url, body: file_content)
# Generate a public (unsigned) URL
MyApp.Storage.public_url("bucket", "photos/cat.jpg")
# Retrieve file metadata
{:ok, %{file_size: 1024, mime_type: "image/jpeg"}} = MyApp.Storage.metadata("bucket", "photos/cat.jpg")Providers
ExOss supports four provider modes:
| Provider | Endpoint | Description |
|---|---|---|
:aws | Auto: s3.{region}.amazonaws.com | Standard AWS S3 |
:qiniu | Auto: s3.{region}.qiniucs.com | Qiniu S3-compatible API |
:aliyun | Auto: {bucket}.oss-{region}.aliyuncs.com | Native OSS V4 |
:custom | Manual: set endpoint | MinIO, DigitalOcean Spaces, Cloudflare R2, etc. |
For custom providers, you must set the endpoint and typically bucket_addressing: :path:
config :my_app, MyApp.MinIO,
provider: :custom,
endpoint: "http://localhost:9000",
bucket_addressing: :path,
access_key_id: "minioadmin",
secret_access_key: "minioadmin"Multi-Client
You can define multiple storage modules for different backends:
defmodule MyApp.AWSStorage do
use ExOss, otp_app: :my_app
end
defmodule MyApp.MinIOStorage do
use ExOss, otp_app: :my_app
end
config :my_app, MyApp.AWSStorage,
provider: :aws,
access_key_id: "...",
secret_access_key: "...",
region: "us-east-1"
config :my_app, MyApp.MinIOStorage,
provider: :custom,
endpoint: "http://localhost:9000",
bucket_addressing: :path,
access_key_id: "minioadmin",
secret_access_key: "minioadmin"Or build clients programmatically:
aws = ExOss.Client.new(provider: :aws, access_key_id: "...", ...)
minio = ExOss.Client.new(provider: :custom, endpoint: "...", ...)
ExOss.Runner.upload_credential(aws, "bucket", "key", 3600)
ExOss.Runner.public_url(minio, "bucket", "key")Next Steps
- Aliyun OSS — native OSS, headers and STS
- Aliyun CDN — A/B/C/F URL authentication
- AWS S3 — detailed AWS S3 configuration
- S3-Compatible Services — MinIO, DigitalOcean, Cloudflare R2
- CloudFront CDN — signed CloudFront URLs
- Qiniu CDN — Qiniu CDN auth tokens
- File Transfer — upload, copy, delete operations