After years of using Phoenix, I finally ran into my first need to generate and then download a file from an endpoint.

I was happy to discover Phoenix.Controller includes an easy was to do this:

def download(conn, params) do
  send_download(conn, {:binary, "world"}, filename: "hello.txt")
end

In this example, Phoenix packages up the file with the contents provided and downloads it.

You can also point to a file, using the {:file, path_to_file} and Phoenix will infer the name and mime type.

My one gripe - Phoenix sends a 200 status code by default. Luckily, you can override that easily by putting your preferred status in the conn:

def download(conn, params) do
  path_to_file = Application.app_dir(:my_app, "priv/prospectus.pdf")

  conn
  |> put_status(:created)
  |> send_download(conn, {:file, path_to_file})
end