Current section
Files
Jump to
Current section
Files
lib/storage/s3.ex
defmodule ExTus.Storage.S3 do
use ExTus.Storage
def storage_dir() do
time = DateTime.utc_now
"#{time.year}/#{time.month}/#{time.day}"
end
def filename(file_name) do
base_name = Path.basename(file_name, Path.extname(file_name))
timestamp = DateTime.utc_now |> DateTime.to_unix
"#{base_name}_#{timestamp}#{Path.extname(file_name)}"
end
def initiate_file(file_name) do
dir = storage_dir()
filename = filename(file_name)
file_path = Path.join([base_dir, dir, filename])
%{bucket: "", path: file_path, opts: [], upload_id: nil}
|> ExAws.S3.Upload.initialize([host: endpoint(bucket())])
|> case do
{:ok, rs} -> {:ok, {rs.upload_id, file_path}}
err -> err
end
end
def put_file(%{filename: _file_path}, _destination) do
end
def append_data(%{identifier: upload_id, filename: file, options: options} = info, data) do
part_id = (options[:current_part] || 0) + 1 #div(info.offset, 5 * 1024 * 1024) + 1 # 5MB each part
""
|> ExAws.S3.upload_part(file, upload_id, part_id, data, ["Content-Length": byte_size(data)])
|> ExAws.request([host: endpoint(bucket())])
|> case do
{:ok, response} ->
%{headers: headers} = response
{_, etag} = Enum.find(headers, fn {k, _v} ->
String.downcase(k) == "etag"
end)
parts = options[:parts] || []
parts = parts ++ [{part_id, etag}]
info = %{info | options: %{parts: parts, current_part: part_id}}
{:ok, info}
err -> err
end
end
def complete_file(%{filename: file, identifier: upload_id, options: options}) do
parts = options[:parts] || []
""
|> ExAws.S3.complete_multipart_upload(
file, upload_id,
Enum.sort_by(parts, &elem(&1, 0))
)
|> ExAws.request([host: endpoint(bucket())])
end
def url(file) do
Path.join asset_host, file
end
def abort_upload(%{identifier: upload_id, filename: file}) do
""
|> ExAws.S3.abort_multipart_upload(file, upload_id)
|> ExAws.request([host: endpoint(bucket())])
end
def delete(file) do
""
|> ExAws.S3.delete_object(file)
|> ExAws.request([host: endpoint(bucket())])
end
defp base_dir() do
Application.get_env(:extus, :base_dir)
end
defp chunk_size do
Application.get_env(:extus, :s3, [])
|> Keyword.get(:chunk_size, 5 * 1024 * 1024)
end
defp bucket do
Application.get_env(:extus, :s3, [])
|> Keyword.get(:bucket)
end
defp virtual_host() do
s3_conf = Application.get_env(:extus, :s3, [])
s3_conf[:virtual_host] || false
end
defp endpoint(bucket) do
"#{bucket}.s3.amazonaws.com"
end
defp host(bucket) do
case virtual_host do
true -> "https://#{bucket}.s3.amazonaws.com"
_ -> "https://s3.amazonaws.com/#{bucket}"
end
end
defp asset_host do
Application.get_env(:extus, :asset_host, host(bucket()))
end
end