Waffle.Storage.Azure (waffle_azure v0.2.0)

Copy Markdown View Source

A Waffle storage adapter for Azure Blob Storage.

config :waffle,
  storage: Waffle.Storage.Azure,
  bucket: "uploads"

config :waffle_azure,
  account: System.get_env("AZURE_ACCOUNT"),
  access_key: System.get_env("AZURE_ACCESS_KEY")

:account and :access_key fall back to the AZURE_ACCOUNT and AZURE_ACCESS_KEY environment variables when they are not configured.

Containers

Waffle's :bucket is the name of the Azure container, which must already exist. As with other Waffle storage adapters, it can be read from the environment with {:system, "VAR"}, or set per uploader by overriding bucket/0 or bucket/1 in the definition module.

URLs

By default, URLs have the form https://<account>.blob.core.windows.net/<container>/<path>. Reading from such a URL needs a container with anonymous read access enabled.

For a private container, generate a read-only shared access signature with signed: true. It expires after 5 minutes unless :expires_in (in seconds) says otherwise:

Avatar.url({"selfie.png", user}, :thumb, signed: true, expires_in: 3600)

To serve files from a CDN, set Waffle's :asset_host. It replaces both the account endpoint and the container, so it should map to the container's root. Signed URLs ignore it, because they are always served by the storage account.

config :waffle,
  asset_host: "https://cdn.example.com"

Blob properties

Blob properties are set through s3_object_headers/2, the hook Waffle provides for object headers. It returns a keyword list or map, and supports these keys:

  • :cache_control
  • :content_disposition
  • :content_encoding
  • :content_language
  • :content_md5
  • :content_type

Lowercase string keys starting with x-ms-, such as "x-ms-access-tier" or "x-ms-meta-owner", are sent as they are. Any other key is ignored, so that a definition can be shared with other storage adapters.

Azure stores blobs as application/octet-stream unless told otherwise, so browsers will download rather than display them without a content type:

def s3_object_headers(_version, {file, _scope}) do
  [content_type: MIME.from_path(file.file_name)]
end

Other options

  • :endpoint - the Blob service URL, for sovereign clouds or the Azurite emulator
  • :request_options - options merged into Req.new/1, such as :receive_timeout

Files larger than 4 MiB and streams are uploaded in blocks of at least 4 MiB. Waffle gives each version 15 seconds to upload by default, so raise its :version_timeout if you expect to store large files.

Summary

Functions

Deletes a file from the container.

Uploads a file to the container.

Builds the URL of an uploaded file.

Functions

delete(definition, version, file_and_scope)

Deletes a file from the container.

The file may be given by name, or by the full URL returned by url/4. Always returns :ok, as Waffle ignores the result. Failures are logged instead.

put(definition, version, arg)

Uploads a file to the container.

Returns {:ok, file_name}, or {:error, reason} where reason is the Req.Response or exception that made the upload fail.

url(definition, version, file_and_scope, options \\ [])

Builds the URL of an uploaded file.

Pass signed: true for a read-only URL that also works on a private container, and :expires_in to set how many seconds it stays valid.