zoeys.computer/lib/zoeyscomputer_web/controllers/image_controller.ex
2024-10-22 16:51:56 -04:00

103 lines
2.7 KiB
Elixir

defmodule ZoeyscomputerWeb.ImageController do
use ZoeyscomputerWeb, :controller
alias Zoeyscomputer.Images
alias Zoeyscomputer.Images.Image
action_fallback ZoeyscomputerWeb.FallbackController
def index(conn, _params) do
images = Images.list_images()
render(conn, :index, images: images)
end
def create(conn, %{"file" => upload}) do
user = conn.assigns.current_user
case handle_upload(upload) do
{:ok, s3_key} ->
# Fixed: create_image takes one argument (the params map)
case Images.create_image(%{file: s3_key, user_id: user.id}) do
{:ok, image} ->
conn
|> put_status(:created)
|> put_resp_header("location", ~p"/api/images/#{image}")
|> json(%{
message: "File uploaded successfully",
url: get_public_url(s3_key),
image: image
})
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> json(%{
error: "Database save failed",
details: changeset_error_to_string(changeset)
})
end
{:error, reason} ->
conn
|> put_status(:unprocessable_entity)
|> json(%{
error: "Upload failed",
reason: inspect(reason)
})
end
end
defp changeset_error_to_string(changeset) do
Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} ->
Enum.reduce(opts, msg, fn {key, value}, acc ->
String.replace(acc, "%{#{key}}", to_string(value))
end)
end)
end
defp handle_upload(upload) do
extension = Path.extname(upload.filename)
id = Nanoid.generate(7)
key = "uploads/#{id}#{extension}"
bucket = "imgs"
{:ok, file_binary} = File.read(upload.path)
case ExAws.S3.put_object(bucket, key, file_binary)
|> ExAws.request() do
{:ok, _response} -> {:ok, id}
{:error, reason} -> {:error, reason}
end
end
defp get_public_url(key) do
"https://zoeys.computer/images/#{key}"
end
def show(conn, %{"id" => id}) do
image = Images.get_image!(id)
render(conn, :show, image: image)
end
def update(conn, %{"id" => id, "image" => image_params}) do
image = Images.get_image!(id)
with {:ok, %Image{} = image} <- Images.update_image(image, image_params) do
render(conn, :show, image: image)
end
end
def delete(conn, %{"id" => id}) do
image = Images.get_image!(id)
case ExAws.S3.delete_object("imgs", image.file)
|> ExAws.request() do
{:ok, _response} -> {:ok, image.file}
{:error, reason} -> {:error, reason}
end
with {:ok, %Image{}} <- Images.delete_image(image) do
send_resp(conn, :no_content, "")
end
end
end