defmodule ComponentsElixirWeb.FileController do use ComponentsElixirWeb, :controller def show(conn, %{"filename" => filename}) do # Security: only allow alphanumeric, dashes, underscores, and dots if String.match?(filename, ~r/^[a-zA-Z0-9_\-\.]+$/) do uploads_dir = Application.get_env(:components_elixir, :uploads_dir) file_path = Path.join([uploads_dir, "images", filename]) if File.exists?(file_path) do # Get the file's MIME type mime_type = get_mime_type(filename) conn |> put_resp_content_type(mime_type) |> put_resp_header("cache-control", "public, max-age=86400") # Cache for 1 day |> send_file(200, file_path) else conn |> put_status(:not_found) |> text("File not found") end else conn |> put_status(:bad_request) |> text("Invalid filename") end end defp get_mime_type(filename) do case Path.extname(filename) |> String.downcase() do ".jpg" -> "image/jpeg" ".jpeg" -> "image/jpeg" ".png" -> "image/png" ".gif" -> "image/gif" ".webp" -> "image/webp" _ -> "application/octet-stream" end end end