diff --git a/lib/phoenix/controller.ex b/lib/phoenix/controller.ex index 95cb139e5e..74f1d5bd46 100644 --- a/lib/phoenix/controller.ex +++ b/lib/phoenix/controller.ex @@ -1274,7 +1274,7 @@ defmodule Phoenix.Controller do end defp encode_filename(filename, false), do: filename - defp encode_filename(filename, true), do: URI.encode(filename) + defp encode_filename(filename, true), do: URI.encode(filename, &URI.char_unreserved?/1) defp get_disposition_type(:attachment), do: "attachment" defp get_disposition_type(:inline), do: "inline" diff --git a/test/phoenix/controller/controller_test.exs b/test/phoenix/controller/controller_test.exs index 279715fa72..4b2057f09c 100644 --- a/test/phoenix/controller/controller_test.exs +++ b/test/phoenix/controller/controller_test.exs @@ -537,6 +537,17 @@ defmodule Phoenix.Controller.ControllerTest do "world" end + test "sends file for download for filename with unreserved characters" do + conn = send_download(conn(:get, "/"), {:file, @hello_txt}, filename: "hello, world.json") + assert conn.status == 200 + assert get_resp_header(conn, "content-disposition") == + ["attachment; filename=\"hello%2C%20world.json\"; filename*=utf-8''hello%2C%20world.json"] + assert get_resp_header(conn, "content-type") == + ["application/json"] + assert conn.resp_body == + "world" + end + test "sends file supports UTF-8" do conn = send_download(conn(:get, "/"), {:file, @hello_txt}, filename: "测 试.txt") assert conn.status == 200