TLDR: Use Phoenix.Controller.send_download/3 to send binary as download to your users.


In Phoenix, there are a couple ways of to send file to your users. The most straightforward one is to programmatically create a file and send it to user using Plug.Conn.send_file/5.

For example:

def export(conn, _params) do
  # Create file
  filename = "test.md"
  File.write(filename, "Hello World")

  # Send file
  conn
  |> put_resp_header("content-disposition", ~s(attachment; filename="#{filename}"))
  |> send_file(200, filename)
end

However, this approach creates a file locally in your production server and require some clean up after that. (I don’t really know how to delete a file only after the request succeed)

Introducing send_download/3

Luckily, there is another approach, which is using Phoenix.Controller.send_download/3. This function allow us to send binary directly as a download. Hence, file creation is not needed.

For example:

def export(conn, _params) do
  filename = "test.md"

  # Send file
  conn
  |> send_download({:binary, "Hello World"}, filename: filename)
end

For more, refer to the send_file/5 and send_download/3 documentation.


This post was first appeared in my TIL web application.