Current section
Files
Jump to
Current section
Files
lib/ivar/files.ex
defmodule Ivar.Files do
@moduledoc """
`Ivar.Files` manages the files to be sent for a request
"""
alias Ivar.Utilities
@valid_types [nil, :multipart, :url_encoded]
@doc """
Puts the given `files` into the existing `request` map
Args
* `request` - the map used to store the map of headers, usually created via `Ivar.new/2`
* `files` - the files to be put into the files list
Files
* tuple - `{"field_name", "some iodata", "file name", "mime type | file extension"}` - the last element of the tuple is optional and the file name will be used to resolve the mime type
* list - a list of tuples in the same format as above
Usage
file_data = File.read!("/some/image.png")
Ivar.Files.put(%{}, {"file", file_data, "image.png"})
# %{files: [{"file", <<1, 2, 3, ...>>, {"form-data", [{"name", "file"}, {"filename", "image.png"}]}, [{"content-type", "image/png"}]}]}
"""
@spec put(map, {tuple | list}) :: map | {:error, binary}
def put(request, files) when is_tuple(files),
do: put(request, [files])
def put(request, files) do
if is_valid?(request) do
request
|> Map.get(:files, [])
|> put_files(files)
|> put_in_request(request)
else
{:error, "Files can only be put into a :url_encoded or :multipart body"}
end
end
defp put_files(files, []), do: files
defp put_files(files, [{name, data, file_name} | rest]) do
mime_type = Utilities.get_mime_type(file_name, :file)
put_files(files, [{name, data, file_name, mime_type} | rest])
end
defp put_files(files, [{name, data, file_name, type} | rest]) do
file = {
name,
IO.iodata_to_binary(data),
{"form-data", [{"name", name}, {"filename", file_name}]},
[{"content-type", Utilities.get_mime_type(type, :ext)}]
}
put_files([file | files], rest)
end
defp put_in_request(files, request),
do: Map.put(request, :files, files)
defp is_valid?(%{body: {type, _, _}}) when type in @valid_types, do: true
defp is_valid?(request), do: request[:body] == nil
end