ExOss.Storage (ExOss v1.2.0)

Copy Markdown View Source

Storage dispatcher for native Aliyun OSS, AWS S3 and S3-compatible services.

Supports four provider modes:

  • :aws — Standard AWS S3 (endpoint auto-constructed as s3.{region}.amazonaws.com)
  • :qiniu — Qiniu S3-compatible API (endpoint auto-constructed as s3.{region}.qiniucs.com)
  • :aliyun — Native OSS V4 authentication (see ExOss.Storage.Aliyun)
  • :custom — Any S3-compatible service (MinIO, DigitalOcean Spaces, Cloudflare R2, etc.) Requires an explicit endpoint to be configured.

S3 storage operations go through ex_aws_s3, using Req as the default HTTP client. For AWS, explicit :ex_aws global or :s3 HTTP client configuration is respected, with :s3 taking precedence.

File Transfer Operations

Use run/2 with an ExOss.StorageTask struct to perform uploads, copies, deletes, and content uploads:

# Upload from local file
ExOss.Storage.run(client, %ExOss.StorageTask{
  source: {:file, "/path/to/file.jpg"},
  target: {:cloud, "bucket", "uploads/file.jpg"}
})

# Upload from remote URL
ExOss.Storage.run(client, %ExOss.StorageTask{
  source: {:remote, "https://example.com/file.jpg"},
  target: {:cloud, "bucket", "uploads/file.jpg"}
})

# Cloud-to-cloud copy
ExOss.Storage.run(client, %ExOss.StorageTask{
  source: {:cloud, "source-bucket", "file.jpg"},
  target: {:cloud, "target-bucket", "copies/file.jpg"}
})

# Delete immediately
ExOss.Storage.run(client, %ExOss.StorageTask{
  source: {:cloud, "bucket", "file.jpg"},
  target: nil
})

# Delete after N days (via lifecycle tags)
ExOss.Storage.run(client, %ExOss.StorageTask{
  source: {:cloud, "bucket", "file.jpg"},
  target: nil,
  opts: [days: 30]
})

Presigned URLs

Generate temporary, direct-access URLs without CDN:

# Download URL (presigned GET)
ExOss.Storage.authorize_download_url(client, "bucket", "file.jpg", 3600)

# Upload URL (presigned PUT)
ExOss.Storage.upload_credential(client, "bucket", "file.jpg", 3600)

When a CDN is configured on the client, use ExOss.Runner instead — it automatically routes to the CDN adapter when cdn_download / cdn_upload are enabled.

Summary

Functions

Resolves and sets the endpoint URL on the client based on the provider.

Generates an S3 presigned download URL for the given resource key.

Retrieves metadata for a stored object via a HEAD request.

Generates zip index content for local zip operations.

Executes a storage task. Upload opts[:headers] are raw HTTP string pairs. String-key "content_type" / "headers" options are also accepted. Explicit headers override legacy content_type and MIME inference. For multipart uploads, object headers are applied to initiation. Provider-specific names and values are passed through without translation.

Generates an S3 or OSS presigned upload URL for the given resource key.

Functions

attach_endpoint(client, bucket)

@spec attach_endpoint(ExOss.Client.Client.t(), binary()) :: ExOss.Client.Client.t()

Resolves and sets the endpoint URL on the client based on the provider.

For :aws and :qiniu, the endpoint is auto-constructed as https://{bucket}.s3.{region}.amazonaws.com (or qiniucs.com).

For :custom, the endpoint must already be set on the client.

authorize_download_url(client, bucket, key, expires, opts)

@spec authorize_download_url(
  ExOss.Client.Client.t(),
  binary(),
  binary(),
  non_neg_integer(),
  ExOss.Options.t()
) :: binary()

Generates an S3 presigned download URL for the given resource key.

Options

  • :query_params — additional query parameters to include in the signed URL
  • :headers — headers to include in the signature
  • :att_name — download disposition for OSS; handled by CDN adapters when supported

Examples

iex> ExOss.Storage.authorize_download_url(client, "bucket", "file.jpg", 3600, [])
"https://bucket.s3.us-east-1.amazonaws.com/file.jpg?X-Amz-..."

metadata(client, bucket, res_key)

@spec metadata(ExOss.Client.Client.t(), binary(), binary()) ::
  {:ok, %{file_size: non_neg_integer(), mime_type: binary()}}
  | {:error, :no_metadata}

Retrieves metadata for a stored object via a HEAD request.

Returns {:ok, %{file_size: integer, mime_type: string}} on success, or {:error, :no_metadata} if the object does not exist or is not accessible.

mkzip_index_content(items)

@spec mkzip_index_content([%{access_address: binary(), alias_name: binary()}]) ::
  binary()

Generates zip index content for local zip operations.

Each item must contain :access_address (the source URL) and :alias_name (the filename inside the zip). Both are Base64 url-safe encoded into the index format expected by ExOss.LocalZipper.zip/1.

Examples

iex> ExOss.Storage.mkzip_index_content([
...>   %{access_address: "https://s3.example.com/1.jpg", alias_name: "img1.jpg"}
...> ])
"/url/aHR0cHM6Ly9zMy5leGFtcGxlLmNvbS8xLmpwZw==/alias/aW1nMS5qcGc="

run(client, task)

Executes a storage task. Upload opts[:headers] are raw HTTP string pairs. String-key "content_type" / "headers" options are also accepted. Explicit headers override legacy content_type and MIME inference. For multipart uploads, object headers are applied to initiation. Provider-specific names and values are passed through without translation.

upload_credential(client, bucket, res_key, expires_in, opts \\ [])

Generates an S3 or OSS presigned upload URL for the given resource key.

Returns an ExOss.UploadCredential struct with the presigned_url field set to a PUT presigned URL. The uptoken field is nil for S3 and OSS. The optional fifth argument accepts :headers and legacy :content_type. Explicit headers win and are returned in credential.headers; the caller must send them with the PUT. No content type is inferred for presigned URLs.

Examples

iex> cred = ExOss.Storage.upload_credential(client, "bucket", "file.jpg", 3600)
iex> cred.presigned_url
"https://bucket.s3.us-east-1.amazonaws.com/file.jpg?X-Amz-..."
iex> cred.uptoken
nil