/cloud-storage

Direct upload with Elixir (wip)

Primary LanguageElixirMIT LicenseMIT

CloudStorage

Direct upload with Elixir / Phoenix

Installation

If available in Hex, the package can be installed by adding cloud_storage to your list of dependencies in mix.exs:

def deps do
  [
    {:cloud_storage, "~> 0.1.0"}
  ]
end

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/cloud_storage.

How it works?

CloudStorage is a direct upload backend and it's compatible with multiple storage. The front end request a presigned url to a configured endpoint, upload the file directly to the storage and let the backend know that the file is correclty uploaded.

Example of presigned url request payload:

{
  "url": "...presigned_url",
  "key": "object_key",
  "reference": "unique reference for the upload"
}

The key is the value that we want to save into our model to reference the upload

Private files

What about orphan uploads?

What is an orphan upload?

Orphan upload is a remote file not used anymore in any of your upload field.

How CloudStorage handle them?

Uploads are tracked using Postgresql trigger function. Each time there is a change on an upload field (ex: avatar), cloud_storage will take care of referencing/dereferencing the corresponding upload. Orphan uploads not updated in the last month are automatically deleted;

Setup

  1. Configurate cloud_storage
# config.exs
config :cloud_storage, :repo, MyApp.Repo
config :cloud_storage, :default_asset_host, "https://cdn.com"
config :cloud_storage, :default_bucket, "mybucket"
config :cloud_storage, :default_storage_dir, "uploads/direct"
  1. Generate migration
mix cloud_storage.install
mix ecto.migrate
  1. Create an uploader
# my_app/uploaders/default_uploader.ex
defmodule MyApp.Uploaders.DefaultUploader do
  use CloudStorage.Uploader
end
  1. Add routes
# my_app_web/router.ex
defmodule MyAppWeb.Router do
  #...
  import CloudStorage.Router

  scope "/api" do
    cloud_storage_routes "/uploads", MyApp.Uploaders.DefaultUploader.Controller
  end

  #...
end
  1. Generate field
mix cloud_storage.gen.upload users avatar
# my_app/users/user.ex
defmodule CloudStorage.User do
  use Ecto.Schema

  schema "users" do
    #...
    field :avatar, MyApp.Uploaders.DefaultUploader.Type

    timestamps()
  end
end
mix ecto.migrate