# `Kotoba.Storage.Local`
[🔗](https://github.com/hattoriai/kotoba/blob/v0.5.0/lib/kotoba/storage/local.ex#L1)

A `Kotoba.Storage` adapter that keeps files in a directory on the local
disk.

    # config/config.exs
    config :kotoba, storage: Kotoba.Storage.Local

    # config/runtime.exs, in the :prod block
    if config_env() == :prod do
      config :kotoba, Kotoba.Storage.Local,
        root: System.get_env("KOTOBA_UPLOADS", "/var/lib/my_app/uploads"),
        url_prefix: "/uploads/kotoba"
    end

    # config/dev.exs
    config :kotoba, Kotoba.Storage.Local, root: Path.expand("../tmp/uploads", __DIR__)

  * `:root` - the directory for the files (required). In production,
    give an absolute path outside the release, from the `:prod` block of
    `config/runtime.exs` (`runtime.exs` runs in every environment, so
    outside that block it replaces the development root). A relative path
    is relative to the current working directory, and in a release the
    files would go into the release directory and be lost on the next
    deploy.
  * `:url_prefix` - the path at which the files are served. The default
    is `"/uploads/kotoba"`. When `Kotoba.Storage.Local.Plug` serves the
    files, this is a path, not a full URL: the plug matches requests
    under it.

Serve the files with `Kotoba.Storage.Local.Plug`. Any other way to serve
them must send `X-Content-Type-Options: nosniff`, a content type from the
allow-list of `Kotoba.Attachments`, and `Content-Disposition: attachment`
for every type that is not an image, a PDF or a video, as the plug does. A key is
always a relative path under the root: a key that
`Kotoba.Storage.valid_key?/1` refuses gives `{:error, :invalid_key}`, so
a key cannot reach a file outside the root.

# `path`

```elixir
@spec path(Kotoba.Storage.key()) :: {:ok, Path.t()} | {:error, :invalid_key}
```

Returns the path on disk of the file with `key`, or
`{:error, :invalid_key}`.

# `root`

```elixir
@spec root() :: Path.t()
```

Returns the configured root directory, as an absolute path.

Raises `ArgumentError` when no root is configured.

# `url_prefix`

```elixir
@spec url_prefix() :: String.t()
```

Returns the configured URL prefix, by default `"/uploads/kotoba"`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
