Packages

phoenix_kit

1.7.39
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib modules storage providers s3.ex
Raw

lib/modules/storage/providers/s3.ex

defmodule PhoenixKit.Modules.Storage.Providers.S3 do
@moduledoc """
AWS S3 storage provider.
Stores files in Amazon S3 buckets using the ExAWS library.
Supports all S3-compatible services (like DigitalOcean Spaces, MinIO, etc.).
"""
@behaviour PhoenixKit.Modules.Storage.Provider
@impl true
def store_file(bucket, source_path, destination_path, opts \\ []) do
# Configure ExAWS with bucket credentials
configure_aws(bucket)
# Upload the file
upload_opts = [
acl: Keyword.get(opts, :acl, "private"),
content_type: Keyword.get(opts, :content_type)
]
case ExAws.S3.upload(source_path, bucket.bucket_name, destination_path, upload_opts)
|> ExAws.request() do
{:ok, _result} ->
url = public_url(bucket, destination_path)
{:ok, url}
{:error, reason} ->
{:error, "Failed to upload to S3: #{inspect(reason)}"}
end
rescue
error -> {:error, "Error storing file to S3: #{inspect(error)}"}
end
@impl true
def retrieve_file(bucket, file_path, destination_path) do
configure_aws(bucket)
# Ensure destination directory exists
destination_dir = Path.dirname(destination_path)
File.mkdir_p!(destination_dir)
# Download the file
case ExAws.S3.download_file(bucket.bucket_name, file_path, destination_path)
|> ExAws.request() do
{:ok, _result} -> :ok
{:error, reason} -> {:error, "Failed to download from S3: #{inspect(reason)}"}
end
rescue
error -> {:error, "Error retrieving file from S3: #{inspect(error)}"}
end
@impl true
def delete_file(bucket, file_path) do
configure_aws(bucket)
case ExAws.S3.delete_object(bucket.bucket_name, file_path) |> ExAws.request() do
{:ok, _result} -> :ok
{:error, reason} -> {:error, "Failed to delete from S3: #{inspect(reason)}"}
end
rescue
error -> {:error, "Error deleting file from S3: #{inspect(error)}"}
end
@impl true
def file_exists?(bucket, file_path) do
configure_aws(bucket)
case ExAws.S3.head_object(bucket.bucket_name, file_path) |> ExAws.request() do
{:ok, _result} -> true
{:error, {:http_error, 404, _}} -> false
{:error, _reason} -> false
end
rescue
_error -> false
end
@impl true
def public_url(bucket, file_path) do
if bucket.cdn_url do
# Use CDN URL if configured
"#{bucket.cdn_url}/#{file_path}"
else
# Use direct S3 URL
region = bucket.region || "us-east-1"
"https://#{bucket.bucket_name}.s3.#{region}.amazonaws.com/#{file_path}"
end
end
@impl true
def test_connection(bucket) do
configure_aws(bucket)
# Test by listing bucket (this requires ListBucket permission)
case ExAws.S3.list_objects(bucket.bucket_name, max_keys: 1) |> ExAws.request() do
{:ok, _result} -> :ok
{:error, {:http_error, 403, _}} -> {:error, "Access denied - check permissions"}
{:error, {:http_error, 404, _}} -> {:error, "Bucket not found"}
{:error, reason} -> {:error, "S3 connection test failed: #{inspect(reason)}"}
end
rescue
error -> {:error, "Error testing S3 connection: #{inspect(error)}"}
end
# Configure ExAWS with bucket-specific credentials
defp configure_aws(bucket) do
config = %{
access_key_id: bucket.access_key_id,
secret_access_key: bucket.secret_access_key,
region: bucket.region || "us-east-1"
}
# Add custom endpoint if specified (for S3-compatible services)
config =
if bucket.endpoint do
Map.put(config, :host, bucket.endpoint)
|> Map.put(:scheme, "https://")
else
config
end
Application.put_env(:ex_aws, :s3, config)
end
end