Current section
Files
Jump to
Current section
Files
lib/azalea/file.ex
defmodule Azalea.File do
@moduledoc """
The file struct need for this module.
* filename, the file's name of the file
* type, the file's content type, eg: :jpg, :png, :gif
* path, the file's path in disk or the key in the cloud
* valid, check if the file is valid
* uploader, the uploader of the file, normally is local or other uploader handler
* module, the module you defined to perform all the operation
* url, the url path of the file, you can get the file through this
"""
alias Elixir.File, as: F
alias Azalea.File, as: AF
defstruct filename: nil, type: nil, path: nil, valid: true,
uploader: nil, module: nil, url: nil, key: nil
@doc """
Cast from other struct, include Map, Plug.Upload, Ecto.Changeset
* params struct of the file you want to convert
* field optional key for you to define which fied of the struct is Azalea.File
"""
def cast_file(params, field \\ nil)
def cast_file(%__MODULE__{} = params, _), do: params
def cast_file(%Ecto.Changeset{} = params, field) do
from_changeset(params, field)
end
def cast_file(%Plug.Upload{} = params, _field) do
from_plug(params)
end
def cast_file(params, _field) when is_map(params) do
make_struct_from(params)
end
def cast_file(_, _), do: invalid_empty_struct
@doc """
Check if the File struct is empty
"""
def is_empty?(struct) do
!struct.filename || !struct.type || !struct.path
end
@doc """
Check if the file is valid
"""
def valid?(file) do
file.valid
end
@doc """
Delete the file data from local disk
"""
def delete(struct) do
if struct.path && Elixir.File.exists?(struct.path) do
Elixir.File.rm_rf!(struct.path)
end
end
@doc """
Save the file to a new position
"""
def save(origin, new)
def save(%AF{valid: false}, _new) do
:error
end
def save(origin, new) do
if origin.path && F.exists?(origin.path) do
dir_name = new.path |> Path.dirname
unless F.exists?(dir_name), do: F.mkdir_p!(dir_name)
case F.cp(origin.path, new.path) do
:ok -> :ok
{:error, _} -> :error
end
else
:error
end
end
defp from_plug(struct) do
if !struct.filename || !struct.content_type || !struct.path do
invalid_empty_struct
else
%AF{empty_struct | type: get_file_type(struct.content_type),
filename: struct.filename, path: struct.path}
end
end
defp from_changeset(struct, field) do
plug_upload = struct |> Ecto.Changeset.get_change(field)
from_plug(plug_upload)
end
def invalid_empty_struct do
%{empty_struct | valid: false}
end
defp empty_struct do
%AF{}
end
# tansform from other struct to Azalea.File
defp make_struct_from(struct)
defp make_struct_from(struct) when is_map(struct) do
case struct do
%{file: path, type: type} ->
struct(AF, %{type: type,
filename: Path.basename(path),
path: path })
_ ->
invalid_empty_struct
end
end
defp make_struct_from(_), do: invalid_empty_struct
defp get_file_type(content_type) do
type =
content_type
|> Plug.Conn.Utils.media_type
|> elem(2)
|> String.to_atom
type = if type == :jpeg, do: :jpg, else: type
type
end
defmacro __using__(_opts) do
quote do
import unquote(__MODULE__)
end
end
end