zoeys.computer/lib/zoeyscomputer_web/controllers/image_controller.ex
2024-10-25 17:17:56 -04:00

117 lines
3.1 KiB
Elixir

defmodule ZoeyscomputerWeb.ImageController do
use ZoeyscomputerWeb, :controller
import Mogrify
alias Zoeyscomputer.IdGenerator
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 = IdGenerator.generate()
key = "uploads/#{id}.png"
bucket = "imgs"
local_path = "/tmp/#{id}#{extension}"
IO.puts("upload path: #{upload.path}")
{:ok, file_binary} = File.read(upload.path)
File.write!(local_path, file_binary)
IO.puts("wrote to #{local_path}")
image = open(local_path) |> format("png") |> save()
IO.inspect(image)
{:ok, new_file_binary} = File.read(image.path)
case ExAws.S3.put_object(bucket, key, new_file_binary, %{content_type: "image/png"})
|> 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