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